Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'android'
- Manifest: browser/modules/test/unit/xpcshell.toml
/* Any copyright is dedicated to the Public Domain.
*/
"use strict";
const { SitePermissions } = ChromeUtils.importESModule(
"resource:///modules/SitePermissions.sys.mjs"
);
const RESIST_FINGERPRINTING_ENABLED = Services.prefs.getBoolPref(
"privacy.resistFingerprinting"
);
const MIDI_ENABLED = Services.prefs.getBoolPref("dom.webmidi.enabled");
const SPEAKER_SELECTION_ENABLED = Services.prefs.getBoolPref(
"media.setsinkid.enabled"
);
add_task(async function testPermissionsListing() {
let expectedPermissions = [
"autoplay-media",
"camera",
"cookie",
"desktop-notification",
"focus-tab-by-prompt",
"geo",
"install",
"microphone",
"popup",
"screen",
"shortcuts",
"persistent-storage",
"storage-access",
"xr",
"3rdPartyStorage",
"3rdPartyFrameStorage",
"open-protocol-handler",
];
if (RESIST_FINGERPRINTING_ENABLED) {
// Canvas permission should be hidden unless privacy.resistFingerprinting
// is true.
expectedPermissions.push("canvas");
}
if (MIDI_ENABLED) {
// Should remove this checking and add it as default after it is fully pref'd-on.
expectedPermissions.push("midi");
expectedPermissions.push("midi-sysex");
}
if (SPEAKER_SELECTION_ENABLED) {
expectedPermissions.push("speaker");
}
Assert.deepEqual(
SitePermissions.listPermissions().sort(),
expectedPermissions.sort(),
"Correct list of all permissions"
);
});
add_task(async function testGetAllByPrincipal() {
// check that it returns an empty array on an invalid principal
// like a principal with an about URI, which doesn't support site permissions
let wrongPrincipal =
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
"about:config"
);
Assert.deepEqual(SitePermissions.getAllByPrincipal(wrongPrincipal), []);
let principal =
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
);
Assert.deepEqual(SitePermissions.getAllByPrincipal(principal), []);
SitePermissions.setForPrincipal(principal, "camera", SitePermissions.ALLOW);
Assert.deepEqual(SitePermissions.getAllByPrincipal(principal), [
{
id: "camera",
state: SitePermissions.ALLOW,
scope: SitePermissions.SCOPE_PERSISTENT,
},
]);
SitePermissions.setForPrincipal(
principal,
"microphone",
SitePermissions.ALLOW,
SitePermissions.SCOPE_SESSION
);
SitePermissions.setForPrincipal(
principal,
"desktop-notification",
SitePermissions.BLOCK
);
Assert.deepEqual(SitePermissions.getAllByPrincipal(principal), [
{
id: "camera",
state: SitePermissions.ALLOW,
scope: SitePermissions.SCOPE_PERSISTENT,
},
{
id: "microphone",
state: SitePermissions.ALLOW,
scope: SitePermissions.SCOPE_SESSION,
},
{
id: "desktop-notification",
state: SitePermissions.BLOCK,
scope: SitePermissions.SCOPE_PERSISTENT,
},
]);
SitePermissions.removeFromPrincipal(principal, "microphone");
Assert.deepEqual(SitePermissions.getAllByPrincipal(principal), [
{
id: "camera",
state: SitePermissions.ALLOW,
scope: SitePermissions.SCOPE_PERSISTENT,
},
{
id: "desktop-notification",
state: SitePermissions.BLOCK,
scope: SitePermissions.SCOPE_PERSISTENT,
},
]);
SitePermissions.removeFromPrincipal(principal, "camera");
SitePermissions.removeFromPrincipal(principal, "desktop-notification");
Assert.deepEqual(SitePermissions.getAllByPrincipal(principal), []);
Assert.equal(Services.prefs.getIntPref("permissions.default.shortcuts"), 0);
SitePermissions.setForPrincipal(
principal,
"shortcuts",
SitePermissions.BLOCK
);
// Customized preference should have been enabled, but the default should not.
Assert.equal(Services.prefs.getIntPref("permissions.default.shortcuts"), 0);
Assert.deepEqual(SitePermissions.getAllByPrincipal(principal), [
{
id: "shortcuts",
state: SitePermissions.BLOCK,
scope: SitePermissions.SCOPE_PERSISTENT,
},
]);
SitePermissions.removeFromPrincipal(principal, "shortcuts");
Services.prefs.clearUserPref("permissions.default.shortcuts");
});
add_task(async function testGetAvailableStates() {
Assert.deepEqual(SitePermissions.getAvailableStates("camera"), [
SitePermissions.UNKNOWN,
SitePermissions.ALLOW,
SitePermissions.BLOCK,
]);
// Test available states with a default permission set.
Services.prefs.setIntPref(
"permissions.default.camera",
SitePermissions.ALLOW
);
Assert.deepEqual(SitePermissions.getAvailableStates("camera"), [
SitePermissions.PROMPT,
SitePermissions.ALLOW,
SitePermissions.BLOCK,
]);
Services.prefs.clearUserPref("permissions.default.camera");
Assert.deepEqual(SitePermissions.getAvailableStates("cookie"), [
SitePermissions.ALLOW,
SitePermissions.ALLOW_COOKIES_FOR_SESSION,
SitePermissions.BLOCK,
]);
Assert.deepEqual(SitePermissions.getAvailableStates("popup"), [
SitePermissions.ALLOW,
SitePermissions.BLOCK,
]);
});
add_task(async function testExactHostMatch() {
let principal =
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
);
let subPrincipal =
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
);
let exactHostMatched = [
"autoplay-media",
"desktop-notification",
"focus-tab-by-prompt",
"camera",
"microphone",
"screen",
"geo",
"xr",
"persistent-storage",
"open-protocol-handler",
];
if (RESIST_FINGERPRINTING_ENABLED) {
// Canvas permission should be hidden unless privacy.resistFingerprinting
// is true.
exactHostMatched.push("canvas");
}
if (MIDI_ENABLED) {
// WebMIDI is only pref'd on in nightly.
// Should remove this checking and add it as default after it is fully pref-on.
exactHostMatched.push("midi");
exactHostMatched.push("midi-sysex");
}
if (SPEAKER_SELECTION_ENABLED) {
exactHostMatched.push("speaker");
}
let nonExactHostMatched = [
"cookie",
"popup",
"install",
"shortcuts",
"storage-access",
"3rdPartyStorage",
"3rdPartyFrameStorage",
];
let permissions = SitePermissions.listPermissions();
for (let permission of permissions) {
SitePermissions.setForPrincipal(
principal,
permission,
SitePermissions.ALLOW
);
if (exactHostMatched.includes(permission)) {
// Check that the sub-origin does not inherit the permission from its parent.
Assert.equal(
SitePermissions.getForPrincipal(subPrincipal, permission).state,
SitePermissions.getDefault(permission),
`${permission} should exact-host match`
);
} else if (nonExactHostMatched.includes(permission)) {
// Check that the sub-origin does inherit the permission from its parent.
Assert.equal(
SitePermissions.getForPrincipal(subPrincipal, permission).state,
SitePermissions.ALLOW,
`${permission} should not exact-host match`
);
} else {
Assert.ok(
false,
`Found an unknown permission ${permission} in exact host match test.` +
"Please add new permissions from SitePermissions.sys.mjs to this test."
);
}
// Check that the permission can be made specific to the sub-origin.
SitePermissions.setForPrincipal(
subPrincipal,
permission,
SitePermissions.PROMPT
);
Assert.equal(
SitePermissions.getForPrincipal(subPrincipal, permission).state,
SitePermissions.PROMPT
);
Assert.equal(
SitePermissions.getForPrincipal(principal, permission).state,
SitePermissions.ALLOW
);
SitePermissions.removeFromPrincipal(subPrincipal, permission);
SitePermissions.removeFromPrincipal(principal, permission);
}
});
add_task(async function testDefaultPrefs() {
let principal =
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
);
// Check that without a pref the default return value is UNKNOWN.
Assert.deepEqual(SitePermissions.getForPrincipal(principal, "camera"), {
state: SitePermissions.UNKNOWN,
scope: SitePermissions.SCOPE_PERSISTENT,
});
// Check that the default return value changed after setting the pref.
Services.prefs.setIntPref(
"permissions.default.camera",
SitePermissions.BLOCK
);
Assert.deepEqual(SitePermissions.getForPrincipal(principal, "camera"), {
state: SitePermissions.BLOCK,
scope: SitePermissions.SCOPE_PERSISTENT,
});
// Check that other permissions still return UNKNOWN.
Assert.deepEqual(SitePermissions.getForPrincipal(principal, "microphone"), {
state: SitePermissions.UNKNOWN,
scope: SitePermissions.SCOPE_PERSISTENT,
});
// Check that the default return value changed after changing the pref.
Services.prefs.setIntPref(
"permissions.default.camera",
SitePermissions.ALLOW
);
Assert.deepEqual(SitePermissions.getForPrincipal(principal, "camera"), {
state: SitePermissions.ALLOW,
scope: SitePermissions.SCOPE_PERSISTENT,
});
// Check that the preference is ignored if there is a value.
SitePermissions.setForPrincipal(principal, "camera", SitePermissions.BLOCK);
Assert.deepEqual(SitePermissions.getForPrincipal(principal, "camera"), {
state: SitePermissions.BLOCK,
scope: SitePermissions.SCOPE_PERSISTENT,
});
// The preference should be honored again, after resetting the permissions.
SitePermissions.removeFromPrincipal(principal, "camera");
Assert.deepEqual(SitePermissions.getForPrincipal(principal, "camera"), {
state: SitePermissions.ALLOW,
scope: SitePermissions.SCOPE_PERSISTENT,
});
// Should be UNKNOWN after clearing the pref.
Services.prefs.clearUserPref("permissions.default.camera");
Assert.deepEqual(SitePermissions.getForPrincipal(principal, "camera"), {
state: SitePermissions.UNKNOWN,
scope: SitePermissions.SCOPE_PERSISTENT,
});
});
add_task(async function testCanvasPermission() {
let resistFingerprinting = Services.prefs.getBoolPref(
"privacy.resistFingerprinting",
false
);
let principal =
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
);
SitePermissions.setForPrincipal(principal, "canvas", SitePermissions.ALLOW);
// Canvas permission is hidden when privacy.resistFingerprinting is false.
Services.prefs.setBoolPref("privacy.resistFingerprinting", false);
Assert.equal(SitePermissions.listPermissions().indexOf("canvas"), -1);
Assert.equal(
SitePermissions.getAllByPrincipal(principal).filter(
permission => permission.id === "canvas"
).length,
0
);
// Canvas permission is visible when privacy.resistFingerprinting is true.
Services.prefs.setBoolPref("privacy.resistFingerprinting", true);
Assert.notEqual(SitePermissions.listPermissions().indexOf("canvas"), -1);
Assert.notEqual(
SitePermissions.getAllByPrincipal(principal).filter(
permission => permission.id === "canvas"
).length,
0
);
SitePermissions.removeFromPrincipal(principal, "canvas");
Services.prefs.setBoolPref(
"privacy.resistFingerprinting",
resistFingerprinting
);
});
add_task(async function testFilePermissions() {
let principal =
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
);
Assert.deepEqual(SitePermissions.getAllByPrincipal(principal), []);
SitePermissions.setForPrincipal(principal, "camera", SitePermissions.ALLOW);
Assert.deepEqual(SitePermissions.getAllByPrincipal(principal), [
{
id: "camera",
state: SitePermissions.ALLOW,
scope: SitePermissions.SCOPE_PERSISTENT,
},
]);
SitePermissions.removeFromPrincipal(principal, "camera");
Assert.deepEqual(SitePermissions.getAllByPrincipal(principal), []);
});