395 lines
12 KiB
JavaScript
395 lines
12 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
|
*/
|
|
"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(
|
|
"https://example.com"
|
|
);
|
|
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(
|
|
"https://example.com"
|
|
);
|
|
let subPrincipal =
|
|
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
|
|
"https://test1.example.com"
|
|
);
|
|
|
|
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(
|
|
"https://example.com"
|
|
);
|
|
|
|
// 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(
|
|
"https://example.com"
|
|
);
|
|
|
|
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(
|
|
"file:///example.js"
|
|
);
|
|
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), []);
|
|
});
|