Browser-Scoped Permissions
Browser-scoped permissions are temporary, per-tab permissions managed directly by the permission manager. They are never persisted to disk and are automatically cleared when the tab is closed.
These permissions were previously managed by SitePermissions.sys.mjs as
“temporary permissions” and have been moved into the C++ permission manager for
better integration with the Permissions API and content processes. Most
consumers (geolocation, notifications, permission UI, etc.) should continue to
go through SitePermissions.sys.mjs
rather than calling the ForBrowser methods directly. SitePermissions
provides higher-level helpers for combining browser-scoped and persistent
permissions and is the expected interface for browser UI code.
Overview
Browser-scoped permissions are keyed by a browser ID (the unique identifier
of a tab’s <xul:browser> element). They are stored in an in-memory hash
table (mBrowserPermissionTable) and are not written to the permissions
database.
Permissions created through this mechanism use the EXPIRE_SESSION_TAB
expiration type and fire the "browser-perm-changed" observer notification
(as opposed to "perm-changed" for regular permissions).
Keying: Origin vs. Site
Browser-scoped permissions use different scoping depending on the permission action:
Deny (
DENY_ACTION) permissions are site-scoped (keyed by base domain). When a user blocks a permission, the block applies to the entire site (e.g., all subdomains ofexample.com). This prevents sites from nagging users with repeated permission requests from different subdomains.All other actions (
ALLOW_ACTION,PROMPT_ACTION, etc.) are origin-scoped. This meanshttps://sub.example.comandhttps://example.comare treated as separate origins, each with their own permission.
When a permission changes between deny and a non-deny action for the same type, the old entry under the other key style is automatically removed.
Lifetime
Browser-scoped permissions have two lifetime mechanisms:
Tab lifetime: All browser-scoped permissions for a tab are automatically removed when the tab’s browsing context is discarded (observed via the
"browsing-context-discarded"notification). Browsing context replacements (e.g., process switches) where the browser ID transfers to a new context are not treated as discards.Timer-based expiry: Permissions can optionally be given a duration in milliseconds. A timer is scheduled in the parent process to automatically remove the permission after the specified duration. The
expireTimeMSparameter toaddFromPrincipalForBrowserspecifies the duration relative to the current time, not an absolute timestamp.
If no expiry duration is specified, the permission lives until the tab is closed.
Interfacing with Browser-Scoped Permissions
Browser-scoped permissions can be accessed through the nsIPermissionManager
interface using the ForBrowser family of methods.
addFromPrincipalForBrowser
Adds a browser-scoped permission for a given principal, type, action, and browser ID. Optionally specify an expiry duration in milliseconds.
let principal = gBrowser.selectedBrowser.contentPrincipal;
let browserId = gBrowser.selectedBrowser.browserId;
// Allow geolocation for this tab (no expiry)
Services.perms.addFromPrincipalForBrowser(
principal,
"geo",
Services.perms.ALLOW_ACTION,
browserId
);
// Block camera for this tab, expires in 1 hour
Services.perms.addFromPrincipalForBrowser(
principal,
"camera",
Services.perms.DENY_ACTION,
browserId,
1000 * 60 * 60
);
testForBrowser
Returns the permission action for a given principal, type, and browser ID.
Returns UNKNOWN_ACTION if no browser-scoped permission is set. Origin-scoped
permissions are checked before site-scoped ones.
let perm = Services.perms.testForBrowser(
principal,
"geo",
browserId
);
if (perm == Services.perms.ALLOW_ACTION) {
// Geolocation is temporarily allowed for this tab
}
removeFromPrincipalForBrowser
Removes a browser-scoped permission. Both origin-scoped and site-scoped keys are tried.
Services.perms.removeFromPrincipalForBrowser(principal, "geo", browserId);
removeAllForBrowser
Removes all browser-scoped permissions for a given browser ID.
Services.perms.removeAllForBrowser(browserId);
removeByActionForBrowser
Removes all browser-scoped permissions with a specific action for a given browser ID. Useful for clearing only blocks or only allows.
// Remove all deny permissions for this tab
Services.perms.removeByActionForBrowser(browserId, Services.perms.DENY_ACTION);
getForBrowser
Returns the browser-scoped permission as an nsIPermission object, or
null if not set.
let perm = Services.perms.getForBrowser(principal, "geo", browserId);
if (perm) {
// perm.capability, perm.expireTime, perm.browserId are available
}
getAllForBrowser
Returns all browser-scoped permissions for a given principal and browser ID as
an array of nsIPermission objects.
let perms = Services.perms.getAllForBrowser(principal, browserId);
copyBrowserPermissions
Copies all browser-scoped permissions from one browser to another. Used during tab-swapping operations.
Services.perms.copyBrowserPermissions(srcBrowserId, destBrowserId);
Observer Notifications
Browser-scoped permission changes fire the "browser-perm-changed"
notification (not "perm-changed"). The subject is an nsIPermission
object with the browserId attribute set, and the data string is one of
"added", "changed", or "deleted".
Interaction with Regular Permissions
When both a browser-scoped permission and a regular (persistent or session-scoped) permission exist for the same principal and type, the browser-scoped permission takes precedence for that tab. Other tabs without a browser-scoped permission will use the regular permission as usual.
The SitePermissions.sys.mjs module provides a higher-level interface that
combines browser-scoped and regular permissions for UI display purposes.