1632 lines
53 KiB
JavaScript
1632 lines
53 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
|
*/
|
|
|
|
/*
|
|
* Test Permission Popup for Sideloaded Extensions.
|
|
*/
|
|
const { AddonTestUtils } = ChromeUtils.importESModule(
|
|
"resource://testing-common/AddonTestUtils.sys.mjs"
|
|
);
|
|
const ADDON_ID = "addon1@test.mozilla.org";
|
|
const CUSTOM_THEME_ID = "theme1@test.mozilla.org";
|
|
const DEFAULT_THEME_ID = "default-theme@mozilla.org";
|
|
|
|
ChromeUtils.defineESModuleGetters(this, {
|
|
PERMISSION_L10N: "resource://gre/modules/ExtensionPermissionMessages.sys.mjs",
|
|
ExtensionPermissions: "resource://gre/modules/ExtensionPermissions.sys.mjs",
|
|
});
|
|
|
|
AddonTestUtils.initMochitest(this);
|
|
|
|
const l10n = new Localization(["browser/browser.ftl"], true);
|
|
const LABEL_FOR_TECHNICAL_AND_INTERACTION_DATA_CHECKBOX = l10n
|
|
.formatMessagesSync([
|
|
"popup-notification-addon-technical-and-interaction-checkbox",
|
|
])[0]
|
|
.attributes.find(attr => attr.name === "label").value;
|
|
|
|
function assertDisabledSideloadedExtensionElement(managerWindow, addonElement) {
|
|
const doc = addonElement.ownerDocument;
|
|
const toggleDisabled = addonElement.querySelector(
|
|
'[action="toggle-disabled"]'
|
|
);
|
|
is(
|
|
doc.l10n.getAttributes(toggleDisabled).id,
|
|
"extension-enable-addon-button-label",
|
|
"Addon toggle-disabled action has the enable label"
|
|
);
|
|
ok(!toggleDisabled.checked, "toggle-disable isn't checked");
|
|
}
|
|
|
|
function assertEnabledSideloadedExtensionElement(managerWindow, addonElement) {
|
|
const doc = addonElement.ownerDocument;
|
|
const toggleDisabled = addonElement.querySelector(
|
|
'[action="toggle-disabled"]'
|
|
);
|
|
is(
|
|
doc.l10n.getAttributes(toggleDisabled).id,
|
|
"extension-enable-addon-button-label",
|
|
"Addon toggle-disabled action has the enable label"
|
|
);
|
|
ok(!toggleDisabled.checked, "toggle-disable isn't checked");
|
|
}
|
|
|
|
function clickEnableExtension(addonElement) {
|
|
addonElement.querySelector('[action="toggle-disabled"]').click();
|
|
}
|
|
|
|
function assertSectionHeaders(popupContentEl, expectedHeaders = []) {
|
|
for (const { id, isVisible, fluentId } of expectedHeaders) {
|
|
const titleEl = popupContentEl.querySelector(`#${id}`);
|
|
ok(titleEl, `Expected element for ${id}`);
|
|
Assert.equal(
|
|
BrowserTestUtils.isVisible(titleEl),
|
|
isVisible,
|
|
`Expected ${id} to${isVisible ? "" : " not"} be visible`
|
|
);
|
|
if (isVisible) {
|
|
Assert.equal(
|
|
titleEl.textContent,
|
|
PERMISSION_L10N.formatValueSync(fluentId),
|
|
`Expected formatted string for ${id}`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test for bug 1647931
|
|
// Install a theme, enable it and then enable the default theme again
|
|
add_task(async function test_theme_enable() {
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["xpinstall.signatures.required", false],
|
|
["extensions.autoDisableScopes", 15],
|
|
],
|
|
});
|
|
|
|
let theme = {
|
|
manifest: {
|
|
browser_specific_settings: { gecko: { id: CUSTOM_THEME_ID } },
|
|
name: "Theme 1",
|
|
theme: {
|
|
colors: {
|
|
frame: "#000000",
|
|
tab_background_text: "#ffffff",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
let xpi = AddonTestUtils.createTempWebExtensionFile(theme);
|
|
await AddonTestUtils.manuallyInstall(xpi);
|
|
|
|
let changePromise = new Promise(resolve =>
|
|
ExtensionsUI.once("change", resolve)
|
|
);
|
|
ExtensionsUI._checkForSideloaded();
|
|
await changePromise;
|
|
|
|
// enable fresh installed theme
|
|
let manager = await open_manager("addons://list/theme");
|
|
let customTheme = getAddonCard(manager, CUSTOM_THEME_ID);
|
|
clickEnableExtension(customTheme);
|
|
|
|
// enable default theme again
|
|
let defaultTheme = getAddonCard(manager, DEFAULT_THEME_ID);
|
|
clickEnableExtension(defaultTheme);
|
|
|
|
let addon = await AddonManager.getAddonByID(CUSTOM_THEME_ID);
|
|
await close_manager(manager);
|
|
await addon.uninstall();
|
|
});
|
|
|
|
// Loading extension by sideloading method
|
|
add_task(async function test_sideloaded_extension_permissions_prompt() {
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["xpinstall.signatures.required", false],
|
|
["extensions.autoDisableScopes", 15],
|
|
],
|
|
});
|
|
|
|
let options = {
|
|
manifest: {
|
|
browser_specific_settings: { gecko: { id: ADDON_ID } },
|
|
name: "Test 1",
|
|
permissions: ["history", "https://*/*"],
|
|
icons: { 64: "foo-icon.png" },
|
|
},
|
|
};
|
|
|
|
let xpi = AddonTestUtils.createTempWebExtensionFile(options);
|
|
await AddonTestUtils.manuallyInstall(xpi);
|
|
|
|
let changePromise = new Promise(resolve =>
|
|
ExtensionsUI.once("change", resolve)
|
|
);
|
|
ExtensionsUI._checkForSideloaded();
|
|
await changePromise;
|
|
|
|
// Test click event on permission cancel option.
|
|
let manager = await open_manager("addons://list/extension");
|
|
let addon = getAddonCard(manager, ADDON_ID);
|
|
|
|
Assert.notEqual(addon, null, "Found sideloaded addon in about:addons");
|
|
|
|
assertDisabledSideloadedExtensionElement(manager, addon);
|
|
|
|
let popupPromise = promisePopupNotificationShown("addon-webext-permissions");
|
|
clickEnableExtension(addon);
|
|
let panel = await popupPromise;
|
|
|
|
ok(PopupNotifications.isPanelOpen, "Permission popup should be visible");
|
|
panel.secondaryButton.click();
|
|
ok(
|
|
!PopupNotifications.isPanelOpen,
|
|
"Permission popup should be closed / closing"
|
|
);
|
|
|
|
addon = await AddonManager.getAddonByID(ADDON_ID);
|
|
ok(
|
|
!addon.seen,
|
|
"Seen flag should remain false after permissions are refused"
|
|
);
|
|
|
|
// Test click event on permission accept option.
|
|
addon = getAddonCard(manager, ADDON_ID);
|
|
Assert.notEqual(addon, null, "Found sideloaded addon in about:addons");
|
|
|
|
assertEnabledSideloadedExtensionElement(manager, addon);
|
|
|
|
popupPromise = promisePopupNotificationShown("addon-webext-permissions");
|
|
clickEnableExtension(addon);
|
|
panel = await popupPromise;
|
|
|
|
ok(PopupNotifications.isPanelOpen, "Permission popup should be visible");
|
|
|
|
let notificationPromise = acceptAppMenuNotificationWhenShown(
|
|
"addon-installed",
|
|
ADDON_ID
|
|
);
|
|
|
|
panel.button.click();
|
|
ok(
|
|
!PopupNotifications.isPanelOpen,
|
|
"Permission popup should be closed / closing"
|
|
);
|
|
await notificationPromise;
|
|
|
|
addon = await AddonManager.getAddonByID(ADDON_ID);
|
|
ok(addon.seen, "Seen flag should be true after permissions are accepted");
|
|
|
|
ok(!PopupNotifications.isPanelOpen, "Permission popup should not be visible");
|
|
|
|
await close_manager(manager);
|
|
await addon.uninstall();
|
|
});
|
|
|
|
add_task(async function testInstallDialogShowsFullDomainsList() {
|
|
const createTestExtensionXPI = ({
|
|
id,
|
|
domainsListLength = 0,
|
|
permissions = [],
|
|
incognito = "spanning",
|
|
}) =>
|
|
AddonTestUtils.createTempWebExtensionFile({
|
|
manifest: {
|
|
// Set the generated id as a name to make it easier to recognize the test case
|
|
// from dialog screenshots (e.g. in the screenshot captured when the test hits
|
|
// a failure).
|
|
name: id,
|
|
version: "1.0",
|
|
browser_specific_settings: {
|
|
gecko: { id },
|
|
},
|
|
incognito,
|
|
permissions: permissions.concat(
|
|
new Array(domainsListLength).fill("examplehost").map((v, i) => {
|
|
return `*://${v}${i}.com/*`;
|
|
})
|
|
),
|
|
},
|
|
});
|
|
|
|
const LONG_DOMAIN_NAME = `averylongdomainname.${new Array(40)
|
|
.fill("x")
|
|
.join("")}.com`;
|
|
|
|
const assertPermsElVisibility = popupContentEl => {
|
|
Assert.equal(
|
|
BrowserTestUtils.isVisible(popupContentEl.permsListEl),
|
|
true,
|
|
"Expect the permissions list element to be visible"
|
|
);
|
|
};
|
|
|
|
const assertNoDomainsList = popupContentEl => {
|
|
const domainsListEl = popupContentEl.querySelector(
|
|
".webext-perm-domains-list"
|
|
);
|
|
Assert.ok(!domainsListEl, "Expect no domain list element to be found");
|
|
};
|
|
|
|
const TEST_CASES = [
|
|
{
|
|
msg: "Test install extension with no host permissions",
|
|
id: "no-domains",
|
|
domainsListLength: 0,
|
|
verifyDialog(popupContentEl, noIncognitoCheckbox) {
|
|
assertSectionHeaders(popupContentEl, [
|
|
{ id: "addon-webext-perm-title-required", isVisible: false },
|
|
{ id: "addon-webext-perm-title-data-collection", isVisible: false },
|
|
{
|
|
id: "addon-webext-perm-title-optional",
|
|
isVisible: !noIncognitoCheckbox,
|
|
fluentId: "webext-perms-header-optional-settings",
|
|
},
|
|
]);
|
|
assertNoDomainsList(popupContentEl);
|
|
Assert.equal(
|
|
BrowserTestUtils.isHidden(popupContentEl.permsListOptionalEl),
|
|
noIncognitoCheckbox,
|
|
`Expect the permissions list element to be ${
|
|
noIncognitoCheckbox ? "hidden" : "visible"
|
|
}`
|
|
);
|
|
},
|
|
},
|
|
{
|
|
msg: "Test install extension with one domain listed in host permissions",
|
|
id: "one-domain",
|
|
domainsListLength: 1,
|
|
verifyDialog(popupContentEl, noIncognitoCheckbox) {
|
|
assertSectionHeaders(popupContentEl, [
|
|
{
|
|
id: "addon-webext-perm-title-required",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-required-perms",
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-data-collection",
|
|
isVisible: false,
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-optional",
|
|
isVisible: !noIncognitoCheckbox,
|
|
fluentId: "webext-perms-header-optional-settings",
|
|
},
|
|
]);
|
|
assertPermsElVisibility(popupContentEl);
|
|
assertNoDomainsList(popupContentEl);
|
|
const hostPermStringEl = popupContentEl.permsListEl.querySelector(
|
|
"li.webext-perm-granted"
|
|
);
|
|
Assert.ok(
|
|
hostPermStringEl,
|
|
"Expect one granted permission string element"
|
|
);
|
|
Assert.equal(
|
|
hostPermStringEl.textContent,
|
|
PERMISSION_L10N.formatValueSync(
|
|
"webext-perms-host-description-one-domain",
|
|
{
|
|
domain: "examplehost0.com",
|
|
}
|
|
),
|
|
"Got the expected host permission string on extension with only one granted domain"
|
|
);
|
|
Assert.ok(
|
|
BrowserTestUtils.isVisible(hostPermStringEl),
|
|
"Expect the host permission string to be visible"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
msg: "Test install extension with less than 6 domains listed in host permissions",
|
|
id: "few-domains",
|
|
domainsListLength: 5,
|
|
verifyDialog(popupContentEl) {
|
|
assertPermsElVisibility(popupContentEl);
|
|
const domainsListEl = popupContentEl.permsListEl.querySelector(
|
|
".webext-perm-domains-list"
|
|
);
|
|
|
|
Assert.ok(
|
|
domainsListEl,
|
|
"Expect domains list element to be found inside the permission list element"
|
|
);
|
|
Assert.ok(
|
|
BrowserTestUtils.isVisible(domainsListEl),
|
|
"Expect the domains list element to be visible"
|
|
);
|
|
Assert.equal(
|
|
domainsListEl.scrollTopMax,
|
|
0,
|
|
"Expect domains list to not be scrollable (chromeOnly scrollTopMax set to 0)"
|
|
);
|
|
// The permission string associated to XUL label element can be reached as labelEl.value.
|
|
Assert.equal(
|
|
domainsListEl.previousElementSibling.value,
|
|
PERMISSION_L10N.formatValueSync(
|
|
"webext-perms-host-description-multiple-domains",
|
|
{
|
|
domainCount: this.domainsListLength,
|
|
}
|
|
),
|
|
`Got the expected host permission string on extension with ${this.domainsListLength} granted domain`
|
|
);
|
|
Assert.deepEqual(
|
|
Array.from(domainsListEl.querySelectorAll("li")).map(
|
|
el => el.textContent
|
|
),
|
|
new Array(this.domainsListLength)
|
|
.fill("examplehost")
|
|
.map((v, i) => `${v}${i}.com`),
|
|
"Got the expected domains listed in the domains list element"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
msg: "Test install extension with many domains listed in host permissions",
|
|
id: "many-domains",
|
|
domainsListLength: 20,
|
|
verifyDialog(popupContentEl) {
|
|
assertPermsElVisibility(popupContentEl);
|
|
const domainsListEl = popupContentEl.permsListEl.querySelector(
|
|
".webext-perm-domains-list"
|
|
);
|
|
|
|
Assert.ok(
|
|
domainsListEl,
|
|
"Expect domains list element to be found inside the permission list element"
|
|
);
|
|
Assert.ok(
|
|
BrowserTestUtils.isVisible(domainsListEl),
|
|
"Expect the domains list element to be visible"
|
|
);
|
|
Assert.greater(
|
|
domainsListEl.scrollTopMax,
|
|
domainsListEl.clientHeight,
|
|
"Expect domains list to be scrollable (chromeOnly scrollTopMax greater than clientHeight)"
|
|
);
|
|
// The permission string associated to XUL label element can be reached as labelEl.value.
|
|
Assert.equal(
|
|
domainsListEl.previousElementSibling.value,
|
|
PERMISSION_L10N.formatValueSync(
|
|
"webext-perms-host-description-multiple-domains",
|
|
{
|
|
domainCount: this.domainsListLength,
|
|
}
|
|
),
|
|
`Got the expected host permission string on extension with ${this.domainsListLength} granted domain`
|
|
);
|
|
Assert.deepEqual(
|
|
Array.from(domainsListEl.querySelectorAll("li")).map(
|
|
el => el.textContent
|
|
),
|
|
new Array(this.domainsListLength)
|
|
.fill("examplehost")
|
|
.map((v, i) => `${v}${i}.com`),
|
|
"Got the expected domains listed in the domains list element"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
msg: "Test text wrapping on a single long domain name",
|
|
id: "one-long-domain",
|
|
domainsListLength: 0,
|
|
permissions: [`*://${LONG_DOMAIN_NAME}/*`],
|
|
verifyDialog(popupContentEl) {
|
|
assertPermsElVisibility(popupContentEl);
|
|
const hostPermStringEl = popupContentEl.permsListEl.querySelector(
|
|
"li.webext-perm-granted"
|
|
);
|
|
Assert.equal(
|
|
hostPermStringEl.childNodes[0].nodeType,
|
|
hostPermStringEl.TEXT_NODE,
|
|
"Expect to have host permission element child to be a text node"
|
|
);
|
|
Assert.equal(
|
|
hostPermStringEl.childNodes[0].nodeValue,
|
|
PERMISSION_L10N.formatValueSync(
|
|
"webext-perms-host-description-one-domain",
|
|
{
|
|
domain: LONG_DOMAIN_NAME,
|
|
}
|
|
),
|
|
"Got the expected host permission string set as the nextNode value"
|
|
);
|
|
Assert.deepEqual(
|
|
// Calling getBoxQuads on the text node is expected to be returning
|
|
// one DOMQuad instance for each line the text node has been broken
|
|
// into (e.g. 3 DOMQuad instances when the long domain name forces
|
|
// the text node to be broken over 3 lines).
|
|
//
|
|
// This check is asserting that none of the lines the text node has
|
|
// been broken into has a width larger than the width of the parent
|
|
// element.
|
|
//
|
|
// NOTE: this assertion is expected to hit a failure if
|
|
// .webext-perm-granted is missing the overflow-wrap CSS rule.
|
|
hostPermStringEl.childNodes[0]
|
|
.getBoxQuads()
|
|
.map(quad => quad.getBounds().width)
|
|
.filter(width => {
|
|
return width > hostPermStringEl.getBoundingClientRect().width;
|
|
}),
|
|
[],
|
|
"The host permission text node should NOT overflow the parent element"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
msg: "Test text wrapping on long domain name in domains list",
|
|
id: "one-long-domain-in-domains-list",
|
|
domainsListLength: 10,
|
|
permissions: [`*://${LONG_DOMAIN_NAME}/*`],
|
|
verifyDialog(popupContentEl) {
|
|
assertPermsElVisibility(popupContentEl);
|
|
const domainsListEl = popupContentEl.permsListEl.querySelector(
|
|
".webext-perm-domains-list"
|
|
);
|
|
Assert.ok(
|
|
domainsListEl,
|
|
"Expect domains list element to be found inside the permission list element"
|
|
);
|
|
Assert.ok(
|
|
BrowserTestUtils.isVisible(domainsListEl),
|
|
"Expect the domains list element to be visible"
|
|
);
|
|
Assert.equal(
|
|
domainsListEl.firstElementChild.childNodes[0].nodeType,
|
|
domainsListEl.TEXT_NODE,
|
|
"Found text node for the long domain name item part of the domain list item"
|
|
);
|
|
Assert.equal(
|
|
domainsListEl.firstElementChild.childNodes[0].nodeValue,
|
|
LONG_DOMAIN_NAME,
|
|
"Got the expected domain name set on the first domain list item"
|
|
);
|
|
Assert.deepEqual(
|
|
// This check is asserting that none of the lines the text node has
|
|
// been broken into has a width larger than the width of the parent
|
|
// element.
|
|
//
|
|
// NOTE: this assertion is expected to hit a failure if .webext-perm-domains-list
|
|
// list items elements are overflowing (e.g. if it is not inheriting the
|
|
// overflow-wrap CSS rule from its ascending notes and doesn't have one set on
|
|
// its own).
|
|
domainsListEl.firstElementChild.childNodes[0]
|
|
.getBoxQuads()
|
|
.map(quad => quad.getBounds().width)
|
|
.filter(width => {
|
|
return (
|
|
width >
|
|
domainsListEl.firstElementChild.getBoundingClientRect().width
|
|
);
|
|
}),
|
|
[],
|
|
"The domain name text node should NOT overflow the parent element"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
msg: "Test wildcard subdomains shown as single host permission",
|
|
id: "with-wildcard-subdomains",
|
|
domainsListLength: 0,
|
|
permissions: ["*://*.example.com/*", "*://example.com/*"],
|
|
verifyDialog(popupContentEl) {
|
|
assertPermsElVisibility(popupContentEl);
|
|
const hostPermStringEl = popupContentEl.permsListEl.querySelector(
|
|
"li.webext-perm-granted"
|
|
);
|
|
Assert.equal(
|
|
hostPermStringEl.textContent,
|
|
PERMISSION_L10N.formatValueSync(
|
|
"webext-perms-host-description-one-domain",
|
|
{
|
|
domain: "example.com",
|
|
}
|
|
),
|
|
"Expected *.example.com and example.com host permissions to be reported as a single domain permission string"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
msg: "Test wildcard subdomains in domains list",
|
|
id: "with-wildcard-subdomains",
|
|
domainsListLength: 0,
|
|
permissions: [
|
|
"*://*.example.com/*",
|
|
"*://example.com/*`",
|
|
"*://*.example.org/*",
|
|
"*://example.org/*",
|
|
],
|
|
verifyDialog(popupContentEl) {
|
|
assertPermsElVisibility(popupContentEl);
|
|
const domainsListEl = popupContentEl.permsListEl.querySelector(
|
|
".webext-perm-domains-list"
|
|
);
|
|
Assert.ok(
|
|
domainsListEl,
|
|
"Expect domains list element to be found inside the permission list element"
|
|
);
|
|
Assert.ok(
|
|
BrowserTestUtils.isVisible(domainsListEl),
|
|
"Expect the domains list element to be visible"
|
|
);
|
|
// Expect the domains list to only include 2 domains and the host permissions string
|
|
// to reflect that as well.
|
|
Assert.deepEqual(
|
|
Array.from(domainsListEl.querySelectorAll("li")).map(
|
|
el => el.textContent
|
|
),
|
|
["example.com", "example.org"],
|
|
"Got the expected domains listed in the domains list element"
|
|
);
|
|
Assert.equal(
|
|
domainsListEl.previousElementSibling.value,
|
|
PERMISSION_L10N.formatValueSync(
|
|
"webext-perms-host-description-multiple-domains",
|
|
{
|
|
domainCount: 2,
|
|
}
|
|
),
|
|
"Got the expected host permission string on extension with 2 granted domain"
|
|
);
|
|
},
|
|
},
|
|
];
|
|
|
|
for (const testCase of TEST_CASES) {
|
|
// Repeat each test without and without the private browsing checkbox
|
|
// (to test the dialog when the host permissions is expected to be part of a list
|
|
// or to be the only permissions listed in the dialog).
|
|
for (const incognito of ["spanning", "not_allowed"]) {
|
|
const noIncognitoCheckbox = incognito === "not_allowed";
|
|
info(
|
|
`${testCase.msg} ${
|
|
noIncognitoCheckbox ? "and no other permissions" : ""
|
|
}`
|
|
);
|
|
const xpi = createTestExtensionXPI({
|
|
...testCase,
|
|
id: `${testCase.id}-with-incognito-${incognito}@test-ext`,
|
|
incognito,
|
|
});
|
|
|
|
await BrowserTestUtils.withNewTab("about:blank", async () => {
|
|
const dialogPromise = promisePopupNotificationShown(
|
|
"addon-webext-permissions"
|
|
);
|
|
|
|
gURLBar.value = xpi.path;
|
|
gURLBar.focus();
|
|
EventUtils.synthesizeKey("KEY_Enter");
|
|
const popupContentEl = await dialogPromise;
|
|
|
|
testCase.verifyDialog(popupContentEl, noIncognitoCheckbox);
|
|
|
|
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
|
|
window.PopupNotifications.panel,
|
|
"popuphidden"
|
|
);
|
|
// hide the panel (this simulates the user dismissing it)
|
|
popupContentEl.closest("panel").hidePopup();
|
|
await popupHiddenPromise;
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
add_task(async function testInstallDialogShowsDataCollectionPermissions() {
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [["extensions.dataCollectionPermissions.enabled", true]],
|
|
});
|
|
|
|
const createTestExtensionXPI = ({
|
|
id,
|
|
manifest_version,
|
|
incognito = undefined,
|
|
permissions = undefined,
|
|
data_collection_permissions = undefined,
|
|
}) => {
|
|
return AddonTestUtils.createTempWebExtensionFile({
|
|
manifest: {
|
|
manifest_version,
|
|
// Set the generated id as a name to make it easier to recognize the
|
|
// test case from dialog screenshots (e.g. in the screenshot captured
|
|
// when the test hits a failure).
|
|
name: id,
|
|
version: "1.0",
|
|
incognito,
|
|
permissions,
|
|
browser_specific_settings: {
|
|
gecko: {
|
|
id,
|
|
data_collection_permissions,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
};
|
|
|
|
const assertHeader = (popupContentEl, extensionId) => {
|
|
Assert.equal(
|
|
popupContentEl.querySelector(".popup-notification-description")
|
|
.textContent,
|
|
PERMISSION_L10N.formatValueSync(
|
|
"webext-perms-header2",
|
|
// We set the extension name to the extension id in `createTestExtensionXPI`.
|
|
{ extension: extensionId }
|
|
),
|
|
"Expected header string"
|
|
);
|
|
};
|
|
|
|
const TEST_CASES = [
|
|
{
|
|
title: "With no data collection and incognito not allowed",
|
|
incognito: "not_allowed",
|
|
verifyDialog(popupContentEl, { extensionId }) {
|
|
assertHeader(popupContentEl, extensionId);
|
|
Assert.equal(
|
|
popupContentEl.introEl.textContent,
|
|
PERMISSION_L10N.formatValueSync("webext-perms-list-intro-unsigned"),
|
|
"Expected list intro string"
|
|
);
|
|
assertSectionHeaders(popupContentEl, [
|
|
{ id: "addon-webext-perm-title-required", isVisible: false },
|
|
{ id: "addon-webext-perm-title-data-collection", isVisible: false },
|
|
{ id: "addon-webext-perm-title-optional", isVisible: false },
|
|
]);
|
|
Assert.equal(
|
|
popupContentEl.permsListEl.childElementCount,
|
|
0,
|
|
"Expected no required permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.childElementCount,
|
|
0,
|
|
"Expected no data collection permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListOptionalEl.childElementCount,
|
|
0,
|
|
"Expected no optional settings"
|
|
);
|
|
Assert.ok(
|
|
!popupContentEl.hasAttribute("learnmoreurl"),
|
|
"Expected no learn more link"
|
|
);
|
|
},
|
|
},
|
|
// Make sure we have the incognito checkbox when no other permissions are
|
|
// specified.
|
|
{
|
|
title: "With no data collection",
|
|
verifyDialog(popupContentEl, { extensionId }) {
|
|
assertHeader(popupContentEl, extensionId);
|
|
assertSectionHeaders(popupContentEl, [
|
|
{ id: "addon-webext-perm-title-required", isVisible: false },
|
|
{ id: "addon-webext-perm-title-data-collection", isVisible: false },
|
|
{
|
|
id: "addon-webext-perm-title-optional",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-optional-settings",
|
|
},
|
|
]);
|
|
Assert.equal(
|
|
popupContentEl.permsListEl.childElementCount,
|
|
0,
|
|
"Expected no required permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.childElementCount,
|
|
0,
|
|
"Expected no data collection permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListOptionalEl.childElementCount,
|
|
1,
|
|
"Expected optional settings"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListOptionalEl.querySelector(
|
|
"li.webext-perm-privatebrowsing > moz-checkbox"
|
|
),
|
|
"Expected private browsing checkbox"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.hasAttribute("learnmoreurl"),
|
|
"Expected a learn more link"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: "With required data collection",
|
|
data_collection_permissions: {
|
|
required: ["locationInfo"],
|
|
},
|
|
verifyDialog(popupContentEl, { extensionId }) {
|
|
assertHeader(popupContentEl, extensionId);
|
|
assertSectionHeaders(popupContentEl, [
|
|
{ id: "addon-webext-perm-title-required", isVisible: false },
|
|
{
|
|
id: "addon-webext-perm-title-data-collection",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-data-collection-perms",
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-optional",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-optional-settings",
|
|
},
|
|
]);
|
|
Assert.equal(
|
|
popupContentEl.permsListEl.childElementCount,
|
|
0,
|
|
"Expected no required permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.childElementCount,
|
|
1,
|
|
"Expected a data collection permission"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListDataCollectionEl.querySelector(
|
|
"li.webext-data-collection-perm-granted"
|
|
),
|
|
"Expected data collection item"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.firstChild.textContent,
|
|
PERMISSION_L10N.formatValueSync(
|
|
"webext-perms-description-data-some",
|
|
{
|
|
permissions: "location",
|
|
}
|
|
),
|
|
"Expected formatted data collection permission string"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListOptionalEl.childElementCount,
|
|
1,
|
|
"Expected optional settings"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListOptionalEl.querySelector(
|
|
"li.webext-perm-privatebrowsing > moz-checkbox"
|
|
),
|
|
"Expected private browsing checkbox"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.hasAttribute("learnmoreurl"),
|
|
"Expected a learn more link"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: "With multiple required data collection",
|
|
data_collection_permissions: {
|
|
required: ["locationInfo", "financialAndPaymentInfo", "websiteContent"],
|
|
},
|
|
verifyDialog(popupContentEl, { extensionId }) {
|
|
assertHeader(popupContentEl, extensionId);
|
|
assertSectionHeaders(popupContentEl, [
|
|
{ id: "addon-webext-perm-title-required", isVisible: false },
|
|
{
|
|
id: "addon-webext-perm-title-data-collection",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-data-collection-perms",
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-optional",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-optional-settings",
|
|
},
|
|
]);
|
|
Assert.equal(
|
|
popupContentEl.permsListEl.childElementCount,
|
|
0,
|
|
"Expected no required permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.childElementCount,
|
|
1,
|
|
"Expected a data collection permission"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.firstChild.textContent,
|
|
PERMISSION_L10N.formatValueSync(
|
|
"webext-perms-description-data-some",
|
|
{
|
|
// We pass the result of the `Intl.ListFormat` here to verify its
|
|
// output.
|
|
permissions:
|
|
"location, financial and payment information, website content",
|
|
}
|
|
),
|
|
"Expected formatted data collection permission string"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListOptionalEl.childElementCount,
|
|
1,
|
|
"Expected optional settings"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListOptionalEl.querySelector(
|
|
"li.webext-perm-privatebrowsing > moz-checkbox"
|
|
),
|
|
"Expected private browsing checkbox"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.hasAttribute("learnmoreurl"),
|
|
"Expected a learn more link"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: "With explicit no data collection",
|
|
data_collection_permissions: {
|
|
required: ["none"],
|
|
},
|
|
verifyDialog(popupContentEl, { extensionId }) {
|
|
assertHeader(popupContentEl, extensionId);
|
|
assertSectionHeaders(popupContentEl, [
|
|
{ id: "addon-webext-perm-title-required", isVisible: false },
|
|
{
|
|
id: "addon-webext-perm-title-data-collection",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-data-collection-is-none",
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-optional",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-optional-settings",
|
|
},
|
|
]);
|
|
Assert.equal(
|
|
popupContentEl.permsListEl.childElementCount,
|
|
0,
|
|
"Expected no required permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.childElementCount,
|
|
1,
|
|
"Expected a data collection permission"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.textContent,
|
|
PERMISSION_L10N.formatValueSync("webext-perms-description-data-none"),
|
|
"Expected formatted data collection permission string"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListOptionalEl.childElementCount,
|
|
1,
|
|
"Expected optional settings"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListOptionalEl.querySelector(
|
|
"li.webext-perm-privatebrowsing > moz-checkbox"
|
|
),
|
|
"Expected private browsing checkbox"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.hasAttribute("learnmoreurl"),
|
|
"Expected a learn more link"
|
|
);
|
|
},
|
|
},
|
|
// This test verifies that we omit "none" when other required data
|
|
// collection permissions are also defined.
|
|
{
|
|
title: "With required data collection and 'none'",
|
|
// This test extension requires "none" with another data collection permission,
|
|
// and so it is expected to log a manifest warning.
|
|
expectManifestWarnings: true,
|
|
data_collection_permissions: {
|
|
required: ["none", "locationInfo"],
|
|
},
|
|
verifyDialog(popupContentEl, { extensionId }) {
|
|
assertHeader(popupContentEl, extensionId);
|
|
assertSectionHeaders(popupContentEl, [
|
|
{ id: "addon-webext-perm-title-required", isVisible: false },
|
|
{
|
|
id: "addon-webext-perm-title-data-collection",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-data-collection-perms",
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-optional",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-optional-settings",
|
|
},
|
|
]);
|
|
Assert.equal(
|
|
popupContentEl.permsListEl.childElementCount,
|
|
0,
|
|
"Expected no required permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.childElementCount,
|
|
1,
|
|
"Expected data collection permission"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.textContent,
|
|
PERMISSION_L10N.formatValueSync(
|
|
"webext-perms-description-data-some",
|
|
{
|
|
permissions: "location",
|
|
}
|
|
),
|
|
"Expected formatted data collection permission string"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListOptionalEl.childElementCount,
|
|
1,
|
|
"Expected optional settings"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListOptionalEl.querySelector(
|
|
"li.webext-perm-privatebrowsing > moz-checkbox"
|
|
),
|
|
"Expected private browsing checkbox"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.hasAttribute("learnmoreurl"),
|
|
"Expected a learn more link"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: "With optional data collection",
|
|
data_collection_permissions: {
|
|
optional: ["locationInfo"],
|
|
},
|
|
verifyDialog(popupContentEl, { extensionId }) {
|
|
assertHeader(popupContentEl, extensionId);
|
|
assertSectionHeaders(popupContentEl, [
|
|
{ id: "addon-webext-perm-title-required", isVisible: false },
|
|
{
|
|
id: "addon-webext-perm-title-data-collection",
|
|
isVisible: false,
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-optional",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-optional-settings",
|
|
},
|
|
]);
|
|
Assert.equal(
|
|
popupContentEl.permsListEl.childElementCount,
|
|
0,
|
|
"Expected no required permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.childElementCount,
|
|
0,
|
|
"Expected no data collection permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListOptionalEl.childElementCount,
|
|
1,
|
|
"Expected optional settings"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListOptionalEl.querySelector(
|
|
"li.webext-perm-privatebrowsing > moz-checkbox"
|
|
),
|
|
"Expected private browsing checkbox"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.hasAttribute("learnmoreurl"),
|
|
"Expected a learn more link"
|
|
);
|
|
},
|
|
},
|
|
// This test case verifies that we show a checkbox for the
|
|
// `technicalAndInteraction` optional data collection permission.
|
|
{
|
|
title: "With technical and interaction data",
|
|
data_collection_permissions: {
|
|
optional: ["technicalAndInteraction"],
|
|
},
|
|
verifyDialog(popupContentEl, { extensionId }) {
|
|
assertHeader(popupContentEl, extensionId);
|
|
assertSectionHeaders(popupContentEl, [
|
|
{ id: "addon-webext-perm-title-required", isVisible: false },
|
|
{
|
|
id: "addon-webext-perm-title-data-collection",
|
|
isVisible: false,
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-optional",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-optional-settings",
|
|
},
|
|
]);
|
|
Assert.equal(
|
|
popupContentEl.permsListEl.childElementCount,
|
|
0,
|
|
"Expected no required permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.childElementCount,
|
|
0,
|
|
"Expected no data collection permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListOptionalEl.childElementCount,
|
|
2,
|
|
"Expected optional settings"
|
|
);
|
|
let checkboxEl = popupContentEl.permsListOptionalEl.querySelector(
|
|
"li.webext-data-collection-perm-optional > moz-checkbox"
|
|
);
|
|
Assert.ok(checkboxEl, "Expected technical and interaction checkbox");
|
|
Assert.ok(checkboxEl.checked, "Expected checkbox to be checked");
|
|
Assert.equal(
|
|
checkboxEl.label,
|
|
LABEL_FOR_TECHNICAL_AND_INTERACTION_DATA_CHECKBOX,
|
|
"Expected formatted data collection permission string"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListOptionalEl.querySelector(
|
|
"li.webext-perm-privatebrowsing > moz-checkbox"
|
|
),
|
|
"Expected private browsing checkbox"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.hasAttribute("learnmoreurl"),
|
|
"Expected a learn more link"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: "With technical and interaction data and no private browsing",
|
|
incognito: "not_allowed",
|
|
data_collection_permissions: {
|
|
optional: ["technicalAndInteraction"],
|
|
},
|
|
verifyDialog(popupContentEl, { extensionId }) {
|
|
assertHeader(popupContentEl, extensionId);
|
|
assertSectionHeaders(popupContentEl, [
|
|
{ id: "addon-webext-perm-title-required", isVisible: false },
|
|
{
|
|
id: "addon-webext-perm-title-data-collection",
|
|
isVisible: false,
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-optional",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-optional-settings",
|
|
},
|
|
]);
|
|
Assert.equal(
|
|
popupContentEl.permsListEl.childElementCount,
|
|
0,
|
|
"Expected no required permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.childElementCount,
|
|
0,
|
|
"Expected no data collection permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListOptionalEl.childElementCount,
|
|
1,
|
|
"Expected optional settings"
|
|
);
|
|
let checkboxEl = popupContentEl.permsListOptionalEl.querySelector(
|
|
"li.webext-data-collection-perm-optional > moz-checkbox"
|
|
);
|
|
Assert.ok(checkboxEl, "Expected technical and interaction checkbox");
|
|
Assert.equal(
|
|
checkboxEl.label,
|
|
LABEL_FOR_TECHNICAL_AND_INTERACTION_DATA_CHECKBOX,
|
|
"Expected formatted data collection permission string"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.hasAttribute("learnmoreurl"),
|
|
"Expected a learn more link"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: "No required data collection and technical and interaction data",
|
|
data_collection_permissions: {
|
|
required: ["none"],
|
|
optional: ["technicalAndInteraction"],
|
|
},
|
|
verifyDialog(popupContentEl, { extensionId }) {
|
|
assertHeader(popupContentEl, extensionId);
|
|
assertSectionHeaders(popupContentEl, [
|
|
{ id: "addon-webext-perm-title-required", isVisible: false },
|
|
{
|
|
id: "addon-webext-perm-title-data-collection",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-data-collection-is-none",
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-optional",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-optional-settings",
|
|
},
|
|
]);
|
|
Assert.equal(
|
|
popupContentEl.permsListEl.childElementCount,
|
|
0,
|
|
"Expected no required permissions"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.childElementCount,
|
|
1,
|
|
"Expected data collection permission"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListOptionalEl.childElementCount,
|
|
2,
|
|
"Expected optional settings"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.firstChild.textContent,
|
|
PERMISSION_L10N.formatValueSync("webext-perms-description-data-none"),
|
|
"Expected formatted data collection permission string"
|
|
);
|
|
const checkboxEl = popupContentEl.permsListOptionalEl.querySelector(
|
|
"li.webext-data-collection-perm-optional > moz-checkbox"
|
|
);
|
|
Assert.ok(checkboxEl, "Expected technical and interaction checkbox");
|
|
Assert.equal(
|
|
checkboxEl.label,
|
|
LABEL_FOR_TECHNICAL_AND_INTERACTION_DATA_CHECKBOX,
|
|
"Expected formatted data collection permission string"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListOptionalEl.querySelector(
|
|
"li.webext-perm-privatebrowsing > moz-checkbox"
|
|
),
|
|
"Expected private browsing checkbox"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.hasAttribute("learnmoreurl"),
|
|
"Expected a learn more link"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: "With required permission and data collection",
|
|
permissions: ["bookmarks"],
|
|
data_collection_permissions: {
|
|
required: ["bookmarksInfo"],
|
|
},
|
|
verifyDialog(popupContentEl, { extensionId }) {
|
|
assertHeader(popupContentEl, extensionId);
|
|
assertSectionHeaders(popupContentEl, [
|
|
{
|
|
id: "addon-webext-perm-title-required",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-required-perms",
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-data-collection",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-data-collection-perms",
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-optional",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-optional-settings",
|
|
},
|
|
]);
|
|
Assert.equal(
|
|
popupContentEl.permsListEl.childElementCount,
|
|
1,
|
|
"Expected required permission"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.childElementCount,
|
|
1,
|
|
"Expected data collection permission"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListOptionalEl.childElementCount,
|
|
1,
|
|
"Expected optional settings"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListEl.firstChild.classList.contains(
|
|
"webext-perm-granted"
|
|
),
|
|
"Expected first entry to be the required API permission"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListDataCollectionEl.querySelector(
|
|
"li.webext-data-collection-perm-granted"
|
|
),
|
|
"Expected data collection item"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.textContent,
|
|
PERMISSION_L10N.formatValueSync(
|
|
"webext-perms-description-data-some",
|
|
{
|
|
permissions: "bookmarks",
|
|
}
|
|
),
|
|
"Expected formatted data collection permission string"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListOptionalEl.querySelector(
|
|
"li.webext-perm-privatebrowsing > moz-checkbox"
|
|
),
|
|
"Expected private browsing checkbox"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.hasAttribute("learnmoreurl"),
|
|
"Expected a learn more link"
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title:
|
|
"With required permission and data collection, and optional collection",
|
|
permissions: ["bookmarks"],
|
|
data_collection_permissions: {
|
|
required: ["bookmarksInfo"],
|
|
optional: ["technicalAndInteraction"],
|
|
},
|
|
verifyDialog(popupContentEl, { extensionId }) {
|
|
assertHeader(popupContentEl, extensionId);
|
|
assertSectionHeaders(popupContentEl, [
|
|
{
|
|
id: "addon-webext-perm-title-required",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-required-perms",
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-data-collection",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-data-collection-perms",
|
|
},
|
|
{
|
|
id: "addon-webext-perm-title-optional",
|
|
isVisible: true,
|
|
fluentId: "webext-perms-header-optional-settings",
|
|
},
|
|
]);
|
|
Assert.equal(
|
|
popupContentEl.permsListEl.childElementCount,
|
|
1,
|
|
"Expected required permission"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.childElementCount,
|
|
1,
|
|
"Expected data collection permission"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListOptionalEl.childElementCount,
|
|
2,
|
|
"Expected optional settings"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListEl.firstChild.classList.contains(
|
|
"webext-perm-granted"
|
|
),
|
|
"Expected first entry to be the required API permission"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.permsListDataCollectionEl.querySelector(
|
|
"li.webext-data-collection-perm-granted"
|
|
),
|
|
"Expected data collection item"
|
|
);
|
|
Assert.equal(
|
|
popupContentEl.permsListDataCollectionEl.textContent,
|
|
PERMISSION_L10N.formatValueSync(
|
|
"webext-perms-description-data-some",
|
|
{
|
|
permissions: "bookmarks",
|
|
}
|
|
),
|
|
"Expected formatted data collection permission string"
|
|
);
|
|
const checkboxEl =
|
|
popupContentEl.permsListOptionalEl.childNodes[0].querySelector(
|
|
"moz-checkbox"
|
|
);
|
|
Assert.ok(checkboxEl, "Expected technical and interaction checkbox");
|
|
Assert.equal(
|
|
checkboxEl.label,
|
|
LABEL_FOR_TECHNICAL_AND_INTERACTION_DATA_CHECKBOX,
|
|
"Expected formatted data collection permission string"
|
|
);
|
|
// Make sure the incognito checkbox is the last item.
|
|
Assert.ok(
|
|
popupContentEl.permsListOptionalEl.childNodes[1].querySelector(
|
|
"li.webext-perm-privatebrowsing > moz-checkbox"
|
|
),
|
|
"Expected private browsing checkbox"
|
|
);
|
|
Assert.ok(
|
|
popupContentEl.hasAttribute("learnmoreurl"),
|
|
"Expected a learn more link"
|
|
);
|
|
},
|
|
},
|
|
];
|
|
|
|
for (const manifest_version of [2, 3]) {
|
|
for (const { title, verifyDialog, ...testCase } of TEST_CASES) {
|
|
info(`MV${manifest_version} - ${title}`);
|
|
|
|
const extensionId = `@${title.toLowerCase().replaceAll(/[^\w]+/g, "-")}`;
|
|
const xpi = createTestExtensionXPI({
|
|
id: extensionId,
|
|
manifest_version,
|
|
...testCase,
|
|
});
|
|
|
|
await BrowserTestUtils.withNewTab("about:blank", async () => {
|
|
const dialogPromise = promisePopupNotificationShown(
|
|
"addon-webext-permissions"
|
|
);
|
|
|
|
if (testCase.expectManifestWarnings) {
|
|
await ExtensionTestUtils.failOnSchemaWarnings(false);
|
|
}
|
|
gURLBar.value = xpi.path;
|
|
gURLBar.focus();
|
|
EventUtils.synthesizeKey("KEY_Enter");
|
|
const popupContentEl = await dialogPromise;
|
|
|
|
verifyDialog(popupContentEl, { extensionId });
|
|
|
|
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
|
|
window.PopupNotifications.panel,
|
|
"popuphidden"
|
|
);
|
|
// Hide the panel (this simulates the user dismissing it).
|
|
popupContentEl.closest("panel").hidePopup();
|
|
await popupHiddenPromise;
|
|
if (testCase.expectManifestWarnings) {
|
|
ExtensionTestUtils.failOnSchemaWarnings(true);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
await SpecialPowers.popPrefEnv();
|
|
});
|
|
|
|
add_task(async function testTechnicalAndInteractionData() {
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [["extensions.dataCollectionPermissions.enabled", true]],
|
|
});
|
|
|
|
const extensionId = "@test-id";
|
|
const extension = AddonTestUtils.createTempWebExtensionFile({
|
|
manifest: {
|
|
version: "1.0",
|
|
browser_specific_settings: {
|
|
gecko: {
|
|
id: extensionId,
|
|
data_collection_permissions: {
|
|
optional: ["technicalAndInteraction"],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
let perms = await ExtensionPermissions.get(extensionId);
|
|
Assert.deepEqual(
|
|
perms,
|
|
{ permissions: [], origins: [], data_collection: [] },
|
|
"Expected no permissions"
|
|
);
|
|
|
|
await BrowserTestUtils.withNewTab("about:blank", async () => {
|
|
const dialogPromise = promisePopupNotificationShown(
|
|
"addon-webext-permissions"
|
|
);
|
|
|
|
gURLBar.value = extension.path;
|
|
gURLBar.focus();
|
|
EventUtils.synthesizeKey("KEY_Enter");
|
|
const popupContentEl = await dialogPromise;
|
|
|
|
// Install the add-on.
|
|
let notificationPromise = acceptAppMenuNotificationWhenShown(
|
|
"addon-installed",
|
|
extensionId
|
|
);
|
|
popupContentEl.button.click();
|
|
await notificationPromise;
|
|
|
|
perms = await ExtensionPermissions.get(extensionId);
|
|
Assert.deepEqual(
|
|
perms,
|
|
{
|
|
permissions: [],
|
|
origins: [],
|
|
data_collection: ["technicalAndInteraction"],
|
|
},
|
|
"Expected data collection permission"
|
|
);
|
|
|
|
const addon = await AddonManager.getAddonByID(extensionId);
|
|
Assert.ok(addon, "Expected add-on");
|
|
await addon.uninstall();
|
|
});
|
|
|
|
// Repeat but uncheck the checkbox this time.
|
|
await BrowserTestUtils.withNewTab("about:blank", async () => {
|
|
const dialogPromise = promisePopupNotificationShown(
|
|
"addon-webext-permissions"
|
|
);
|
|
|
|
gURLBar.value = extension.path;
|
|
gURLBar.focus();
|
|
EventUtils.synthesizeKey("KEY_Enter");
|
|
const popupContentEl = await dialogPromise;
|
|
|
|
const checkboxEl = popupContentEl.permsListOptionalEl.querySelector(
|
|
"li.webext-data-collection-perm-optional > moz-checkbox"
|
|
);
|
|
checkboxEl.click();
|
|
|
|
// Install the add-on.
|
|
let notificationPromise = acceptAppMenuNotificationWhenShown(
|
|
"addon-installed",
|
|
extensionId
|
|
);
|
|
popupContentEl.button.click();
|
|
await notificationPromise;
|
|
|
|
perms = await ExtensionPermissions.get(extensionId);
|
|
Assert.deepEqual(
|
|
perms,
|
|
{
|
|
permissions: [],
|
|
origins: [],
|
|
data_collection: [],
|
|
},
|
|
"Expected no data collection permission"
|
|
);
|
|
|
|
const addon = await AddonManager.getAddonByID(extensionId);
|
|
Assert.ok(addon, "Expected add-on");
|
|
await addon.uninstall();
|
|
});
|
|
|
|
await SpecialPowers.popPrefEnv();
|
|
});
|
|
|
|
add_task(async function testVerifyPostInstallPopupWithDataCollection() {
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [["extensions.dataCollectionPermissions.enabled", true]],
|
|
});
|
|
|
|
const extensionId = "@test-id";
|
|
const extension = AddonTestUtils.createTempWebExtensionFile({
|
|
manifest: {
|
|
browser_specific_settings: {
|
|
gecko: { id: extensionId },
|
|
},
|
|
},
|
|
});
|
|
await BrowserTestUtils.withNewTab(
|
|
{ gBrowser, url: "about:robots" },
|
|
async () => {
|
|
const dialogPromise = promisePopupNotificationShown(
|
|
"addon-webext-permissions"
|
|
);
|
|
gURLBar.value = extension.path;
|
|
gURLBar.focus();
|
|
EventUtils.synthesizeKey("KEY_Enter");
|
|
const popupContentEl = await dialogPromise;
|
|
|
|
// Install the add-on.
|
|
let notificationPromise = waitAppMenuNotificationShown(
|
|
"addon-installed",
|
|
extensionId
|
|
);
|
|
popupContentEl.button.click();
|
|
let notification = await notificationPromise;
|
|
|
|
// Verify the post-install popup.
|
|
Assert.ok(
|
|
notification
|
|
.querySelector("#addon-install-description")
|
|
.textContent.startsWith(
|
|
"Update permissions and data preferences any time"
|
|
),
|
|
"Expected notification content with data collection"
|
|
);
|
|
let settingsLink = notification.querySelector(
|
|
"#addon-install-description > a"
|
|
);
|
|
Assert.ok(settingsLink, "Expected a link in the post-install popup");
|
|
const tabPromise = BrowserTestUtils.waitForNewTab(
|
|
gBrowser,
|
|
"about:addons",
|
|
true
|
|
);
|
|
settingsLink.click();
|
|
const tab = await tabPromise;
|
|
Assert.ok(tab, "Expected tab");
|
|
is(
|
|
gBrowser.selectedBrowser.contentWindow.gViewController.currentViewId,
|
|
`addons://detail/${encodeURIComponent(extensionId)}`,
|
|
"Expected about:addons to show the detail view of the extension"
|
|
);
|
|
BrowserTestUtils.removeTab(tab);
|
|
|
|
// Dismiss the popup by clicking "OK".
|
|
notification.button.click();
|
|
|
|
const addon = await AddonManager.getAddonByID(extensionId);
|
|
Assert.ok(addon, "Expected add-on");
|
|
await addon.uninstall();
|
|
}
|
|
);
|
|
|
|
// Same as above with keyboard navigation.
|
|
await BrowserTestUtils.withNewTab(
|
|
{ gBrowser, url: "about:robots" },
|
|
async () => {
|
|
const dialogPromise = promisePopupNotificationShown(
|
|
"addon-webext-permissions"
|
|
);
|
|
gURLBar.value = extension.path;
|
|
gURLBar.focus();
|
|
EventUtils.synthesizeKey("KEY_Enter");
|
|
const popupContentEl = await dialogPromise;
|
|
|
|
// Install the add-on.
|
|
let notificationPromise = waitAppMenuNotificationShown(
|
|
"addon-installed",
|
|
extensionId
|
|
);
|
|
popupContentEl.button.click();
|
|
let notification = await notificationPromise;
|
|
|
|
// Verify the post-install popup.
|
|
let settingsLink = notification.querySelector(
|
|
"#addon-install-description > a"
|
|
);
|
|
Assert.ok(settingsLink, "Expected a link in the post-install popup");
|
|
const tabPromise = BrowserTestUtils.waitForNewTab(
|
|
gBrowser,
|
|
"about:addons",
|
|
true
|
|
);
|
|
const focused = BrowserTestUtils.waitForEvent(settingsLink, "focus");
|
|
settingsLink.focus();
|
|
await focused;
|
|
EventUtils.synthesizeKey("KEY_Enter");
|
|
const tab = await tabPromise;
|
|
Assert.ok(tab, "Expected tab");
|
|
is(
|
|
gBrowser.selectedBrowser.contentWindow.gViewController.currentViewId,
|
|
`addons://detail/${encodeURIComponent(extensionId)}`,
|
|
"Expected about:addons to show the detail view of the extension"
|
|
);
|
|
BrowserTestUtils.removeTab(tab);
|
|
|
|
// Dismiss the popup by clicking "OK".
|
|
notification.button.click();
|
|
|
|
const addon = await AddonManager.getAddonByID(extensionId);
|
|
Assert.ok(addon, "Expected add-on");
|
|
await addon.uninstall();
|
|
}
|
|
);
|
|
|
|
await SpecialPowers.popPrefEnv();
|
|
});
|