commit ace97753a39d1c1c5c60e06930e4b9f8bbc1305e
parent 6456a9a5ef16260ea4d336cfcf2ac0a47adc6ce5
Author: smayya <smayya@mozilla.com>
Date: Sat, 13 Dec 2025 22:46:37 +0000
Bug 2002810 - Add 5-minute timeout for Local Network Access permission prompts. r=emz
Add automatic timeout handling to LNA (Local Network Access) permission prompts
to prevent prompts from remaining on screen indefinitely. If the user doesn't
respond within 5 minutes, the prompt is automatically dismissed and the network
request fails.
Implementation:
- Created LNAPermissionPromptBase class extending PermissionPromptForRequest
- Added timeout logic using lazy.setTimeout from Timer module
- LocalHostPermissionPrompt and LocalNetworkPermissionPrompt now extend the base class
- When timeout expires: dismisses UI popup via PopupNotifications.remove() and cancels request
- Timer is cleared when user responds (Allow/Cancel) or prompt is dismissed
Differential Revision: https://phabricator.services.mozilla.com/D274411
Diffstat:
2 files changed, 88 insertions(+), 11 deletions(-)
diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
@@ -1337,6 +1337,9 @@ pref("network.captive-portal-service.enabled", true);
// If true, network link events will change the value of navigator.onLine
pref("network.manage-offline-status", true);
+// timeout for local network access prompts
+pref("network.lna.prompt.timeout", 300000); // 5 minutes
+
// We want to make sure mail URLs are handled externally...
pref("network.protocol-handler.external.mailto", true); // for mail
diff --git a/browser/modules/PermissionUI.sys.mjs b/browser/modules/PermissionUI.sys.mjs
@@ -72,6 +72,8 @@ ChromeUtils.defineESModuleGetters(lazy, {
AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
SitePermissions: "resource:///modules/SitePermissions.sys.mjs",
+ clearTimeout: "resource://gre/modules/Timer.sys.mjs",
+ setTimeout: "resource://gre/modules/Timer.sys.mjs",
});
XPCOMUtils.defineLazyServiceGetter(
@@ -112,6 +114,13 @@ XPCOMUtils.defineLazyPreferenceGetter(
false
);
+XPCOMUtils.defineLazyPreferenceGetter(
+ lazy,
+ "lnaPromptTimeoutMs",
+ "network.lna.prompt.timeout",
+ 300000
+);
+
/**
* PermissionPrompt should be subclassed by callers that
* want to display prompts to the user. See each method and property
@@ -1009,18 +1018,88 @@ class XRPermissionPrompt extends PermissionPromptForRequest {
}
/**
- * Creates a PermissionPrompt for a nsIContentPermissionRequest for
- * the Local Host Access.
+ * Base class for Local Network Access (LNA) permission prompts.
+ * Provides automatic timeout handling for LNA prompts.
*
- * @param request (nsIContentPermissionRequest)
- * The request for a permission from content.
+ * If the user doesn't respond to the prompt within the timeout period,
+ * the prompt is automatically cancelled and the network request fails.
*/
-class LocalHostPermissionPrompt extends PermissionPromptForRequest {
+class LNAPermissionPromptBase extends PermissionPromptForRequest {
+ static DEFAULT_PROMPT_TIMEOUT_MS = 300000;
+
+ #timeoutTimer = null;
+
constructor(request) {
super();
this.request = request;
}
+ onShown() {
+ this.#startTimeoutTimer();
+ }
+
+ onAfterShow() {
+ this.#clearTimeoutTimer();
+ }
+
+ cancel() {
+ super.cancel();
+ }
+
+ allow(choices) {
+ super.allow(choices);
+ }
+
+ #startTimeoutTimer() {
+ this.#clearTimeoutTimer();
+
+ this.#timeoutTimer = lazy.setTimeout(() => {
+ let scriptError = Cc["@mozilla.org/scripterror;1"].createInstance(
+ Ci.nsIScriptError
+ );
+ scriptError.initWithWindowID(
+ `LNA permission prompt timed out after ${lazy.lnaPromptTimeoutMs / 1000} seconds`,
+ null,
+ 0,
+ 0,
+ Ci.nsIScriptError.warningFlag,
+ "content javascript",
+ this.browser.browsingContext.currentWindowGlobal.innerWindowId
+ );
+ Services.console.logMessage(scriptError);
+
+ this.#removePrompt();
+ this.cancel();
+ }, lazy.lnaPromptTimeoutMs);
+ }
+
+ #removePrompt() {
+ let chromeWin = this.browser?.ownerGlobal;
+ let notification = chromeWin?.PopupNotifications.getNotification(
+ this.notificationID,
+ this.browser
+ );
+ if (notification) {
+ chromeWin.PopupNotifications.remove(notification);
+ }
+ }
+
+ #clearTimeoutTimer() {
+ if (this.#timeoutTimer) {
+ lazy.clearTimeout(this.#timeoutTimer);
+ this.#timeoutTimer = null;
+ }
+ }
+}
+
+/**
+ * Creates a PermissionPrompt for a nsIContentPermissionRequest for
+ * the Local Host Access.
+ *
+ * @param request (nsIContentPermissionRequest)
+ * The request for a permission from content.
+ */
+class LocalHostPermissionPrompt extends LNAPermissionPromptBase {
get type() {
return "localhost";
}
@@ -1240,12 +1319,7 @@ class DesktopNotificationPermissionPrompt extends PermissionPromptForRequest {
* @param request (nsIContentPermissionRequest)
* The request for a permission from content.
*/
-class LocalNetworkPermissionPrompt extends PermissionPromptForRequest {
- constructor(request) {
- super();
- this.request = request;
- }
-
+class LocalNetworkPermissionPrompt extends LNAPermissionPromptBase {
get type() {
return "local-network";
}