commit 936fdf8ebfa062e69864b34fee89521500eaa031
parent c2ef83ec4b8ba8a680b84b598df8097e94e2226a
Author: Andrea Marchesini <amarchesini@mozilla.com>
Date: Wed, 1 Oct 2025 14:08:58 +0000
Bug 1991700 - Fix the ipp add-on navigation logic, r=jaws
Differential Revision: https://phabricator.services.mozilla.com/D266866
Diffstat:
2 files changed, 87 insertions(+), 32 deletions(-)
diff --git a/browser/extensions/ipp-activator/extension/api/parent/ext-ipp.js b/browser/extensions/ipp-activator/extension/api/parent/ext-ipp.js
@@ -180,7 +180,7 @@ this.ippActivator = class extends ExtensionAPI {
const browser = tab?.linkedBrowser;
const win = browser?.ownerGlobal;
if (!browser || !win || !win.gBrowser) {
- return;
+ return Promise.resolve(false);
}
const nbox = win.gBrowser.getNotificationBox(browser);
@@ -215,22 +215,37 @@ this.ippActivator = class extends ExtensionAPI {
const label = buildLabel(message);
- const notification = await nbox.appendNotification(
- id,
- {
- // If label is a string, pass it through; if it's a Node, the
- // notification box will handle it as rich content.
- label,
- priority: nbox.PRIORITY_WARNING_HIGH,
- },
- []
- );
+ // Promise that resolves when the notification is dismissed
+ let resolveDismiss;
+ const dismissedPromise = new Promise(resolve => {
+ resolveDismiss = resolve;
+ });
+
+ // Create the notification; set persistence when available
+ nbox
+ .appendNotification(
+ id,
+ {
+ // If label is a string, pass it through; if it's a Node, the
+ // notification box will handle it as rich content.
+ label,
+ priority: nbox.PRIORITY_WARNING_HIGH,
+ eventCallback: param => {
+ resolveDismiss(param === "dismissed");
+ },
+ },
+ []
+ )
+ .then(notification => {
+ // Persist the notification until the user removes so it
+ // doesn't get removed on redirects.
+ notification.persistence = -1;
+ });
- // Persist the notification until the user removes so it
- // doesn't get removed on redirects.
- notification.persistence = -1;
+ return dismissedPromise;
} catch (e) {
console.warn("Unable to show the message", e);
+ return Promise.resolve(false);
}
},
onDynamicTabBreakagesUpdated: new ExtensionCommon.EventManager({
diff --git a/browser/extensions/ipp-activator/extension/bg.js b/browser/extensions/ipp-activator/extension/bg.js
@@ -74,6 +74,14 @@ class IPPAddonActivator {
this.#unregisterListeners();
+ // When IPP is deactivated, mark currently shown banners as consumed
+ const uniqueDomains = new Set(this.#shownDomainByTab.values());
+ await Promise.allSettled(
+ Array.from(uniqueDomains).map(d =>
+ browser.ippActivator.addNotifiedDomain(d)
+ )
+ );
+
const ids = Array.from(this.#shownDomainByTab.keys());
await Promise.allSettled(
ids.map(id => browser.ippActivator.hideMessage(id))
@@ -206,7 +214,11 @@ class IPPAddonActivator {
changeInfo.url || tab?.url || ""
);
const shownBase = this.#shownDomainByTab.get(tabId);
- if (shownBase && shownBase !== info.baseDomain) {
+ if (
+ shownBase &&
+ shownBase !== info.baseDomain &&
+ shownBase !== info.host
+ ) {
await browser.ippActivator.hideMessage(tabId);
this.#shownDomainByTab.delete(tabId);
}
@@ -278,22 +290,24 @@ class IPPAddonActivator {
return false;
}
- // Do not show the same notification again for the same base domain.
- const shown = await browser.ippActivator.getNotifiedDomains();
- if (
- info.baseDomain &&
- Array.isArray(shown) &&
- shown.includes(info.baseDomain)
- ) {
- return false;
- }
-
- const breakage = breakages.find(
- b =>
- Array.isArray(b.domains) &&
- (b.domains.includes(info.baseDomain) || b.domains.includes(info.host))
+ let domain = info.baseDomain;
+ let breakage = breakages.find(
+ b => Array.isArray(b.domains) && b.domains.includes(info.baseDomain)
);
if (!breakage) {
+ breakage = breakages.find(
+ b => Array.isArray(b.domains) && b.domains.includes(info.host)
+ );
+ if (!breakage) {
+ return false;
+ }
+
+ domain = info.host;
+ }
+
+ // Do not show the same notification again for the same base domain.
+ const shown = await browser.ippActivator.getNotifiedDomains();
+ if (Array.isArray(shown) && shown.includes(domain)) {
return false;
}
@@ -303,11 +317,37 @@ class IPPAddonActivator {
return false;
}
- await browser.ippActivator.showMessage(breakage.message, tab.id);
// Track which base domain this tab is showing a notification for
- this.#shownDomainByTab.set(tab.id, info.baseDomain);
+ this.#shownDomainByTab.set(tab.id, domain);
+
+ // This function returns when the notification is dismissed. We don't want
+ // to wait for that to happen.
+ browser.ippActivator
+ .showMessage(breakage.message, tab.id)
+ .then(async dismissed => {
+ if (!dismissed) {
+ return;
+ }
+
+ await browser.ippActivator.addNotifiedDomain(domain);
- await browser.ippActivator.addNotifiedDomain(info.baseDomain);
+ // Close all notifications currently shown for the same base domain
+ // across all tabs and clean up tracking state.
+ const toClose = [];
+ for (const [tid, base] of this.#shownDomainByTab.entries()) {
+ if (base === domain) {
+ toClose.push(tid);
+ }
+ }
+
+ await Promise.allSettled(
+ toClose.map(id => browser.ippActivator.hideMessage(id))
+ );
+
+ for (const id of toClose) {
+ this.#shownDomainByTab.delete(id);
+ }
+ });
return true;
}