--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -76,16 +76,18 @@ support-files =
zoom_test.html
file_install_extensions.html
browser_webext_permissions.xpi
browser_webext_nopermissions.xpi
browser_webext_update1.xpi
browser_webext_update2.xpi
browser_webext_update_icon1.xpi
browser_webext_update_icon2.xpi
+ browser_webext_update_perms1.xpi
+ browser_webext_update_perms2.xpi
browser_webext_update.json
!/image/test/mochitest/blue.png
!/toolkit/content/tests/browser/common/mockTransfer.js
!/toolkit/modules/tests/browser/metadata_*.html
!/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi
!/toolkit/mozapps/extensions/test/xpinstall/corrupt.xpi
!/toolkit/mozapps/extensions/test/xpinstall/incompatible.xpi
!/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html
--- a/browser/base/content/test/general/browser_extension_sideloading.js
+++ b/browser/base/content/test/general/browser_extension_sideloading.js
@@ -66,35 +66,16 @@ class MockProvider {
let addons = [];
if (!types || types.includes("extension")) {
addons = [...this.addons];
}
callback(addons);
}
}
-function promiseViewLoaded(tab, viewid) {
- let win = tab.linkedBrowser.contentWindow;
- if (win.gViewController && !win.gViewController.isLoading &&
- win.gViewController.currentViewId == viewid) {
- return Promise.resolve();
- }
-
- return new Promise(resolve => {
- function listener() {
- if (win.gViewController.currentViewId != viewid) {
- return;
- }
- win.document.removeEventListener("ViewChanged", listener);
- resolve();
- }
- win.document.addEventListener("ViewChanged", listener);
- });
-}
-
function promisePopupNotificationShown(name) {
return new Promise(resolve => {
function popupshown() {
let notification = PopupNotifications.getNotification(name);
if (!notification) {
return;
}
@@ -164,16 +145,27 @@ add_task(function* () {
AddonManagerPrivate.unregisterProvider(provider);
// clear out ExtensionsUI state about sideloaded extensions so
// subsequent tests don't get confused.
ExtensionsUI.sideloaded.clear();
ExtensionsUI.emit("change");
});
+ // Navigate away from the starting page to force about:addons to load
+ // in a new tab during the tests below.
+ gBrowser.selectedBrowser.loadURI("about:robots");
+ yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
+
+ registerCleanupFunction(function*() {
+ // Return to about:blank when we're done
+ gBrowser.selectedBrowser.loadURI("about:blank");
+ yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
+ });
+
let changePromise = new Promise(resolve => {
ExtensionsUI.on("change", function listener() {
ExtensionsUI.off("change", listener);
resolve();
});
});
ExtensionsUI._checkForSideloaded();
yield changePromise;
@@ -184,77 +176,73 @@ add_task(function* () {
// Find the menu entries for sideloaded extensions
yield PanelUI.show();
let addons = document.getElementById("PanelUI-footer-addons");
is(addons.children.length, 2, "Have 2 menu entries for sideloaded extensions");
// Click the first sideloaded extension
- let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:addons");
let popupPromise = promisePopupNotificationShown("addon-webext-permissions");
addons.children[0].click();
- // about:addons should load and go to the list of extensions
- let tab = yield tabPromise;
- is(tab.linkedBrowser.currentURI.spec, "about:addons", "Newly opened tab is at about:addons");
+ // When we get the permissions prompt, we should be at the extensions
+ // list in about:addons
+ let panel = yield popupPromise;
+ is(gBrowser.currentURI.spec, "about:addons", "Foreground tab is at about:addons");
const VIEW = "addons://list/extension";
- yield promiseViewLoaded(tab, VIEW);
- let win = tab.linkedBrowser.contentWindow;
+ let win = gBrowser.selectedBrowser.contentWindow;
ok(!win.gViewController.isLoading, "about:addons view is fully loaded");
is(win.gViewController.currentViewId, VIEW, "about:addons is at extensions list");
- // Wait for the permission prompt and cancel it
- let panel = yield popupPromise;
+ // Check the contents of the notification, then choose "Cancel"
let icon = panel.getAttribute("icon");
is(icon, ICON_URL, "Permissions notification has the addon icon");
let disablePromise = promiseSetDisabled(mock1);
panel.secondaryButton.click();
let value = yield disablePromise;
is(value, true, "Addon should remain disabled");
let [addon1, addon2] = yield AddonManager.getAddonsByIDs([ID1, ID2]);
ok(addon1.seen, "Addon should be marked as seen");
is(addon1.userDisabled, true, "Addon 1 should still be disabled");
is(addon2.userDisabled, true, "Addon 2 should still be disabled");
- yield BrowserTestUtils.removeTab(tab);
+ yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
// Should still have 1 entry in the hamburger menu
yield PanelUI.show();
addons = document.getElementById("PanelUI-footer-addons");
is(addons.children.length, 1, "Have 1 menu entry for sideloaded extensions");
- // Click the second sideloaded extension
- tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:addons");
+ // Click the second sideloaded extension and wait for the notification
popupPromise = promisePopupNotificationShown("addon-webext-permissions");
addons.children[0].click();
-
- tab = yield tabPromise;
- is(tab.linkedBrowser.currentURI.spec, "about:addons", "Newly opened tab is at about:addons");
+ panel = yield popupPromise;
isnot(menuButton.getAttribute("badge-status"), "addon-alert", "Should no longer have addon alert badge");
- yield promiseViewLoaded(tab, VIEW);
- win = tab.linkedBrowser.contentWindow;
+ // Again we should be at the extentions list in about:addons
+ is(gBrowser.currentURI.spec, "about:addons", "Foreground tab is at about:addons");
+
+ win = gBrowser.selectedBrowser.contentWindow;
ok(!win.gViewController.isLoading, "about:addons view is fully loaded");
is(win.gViewController.currentViewId, VIEW, "about:addons is at extensions list");
- // Wait for the permission prompt and accept it this time
- panel = yield popupPromise;
+ // Check the notification contents, this time accept the install
icon = panel.getAttribute("icon");
is(icon, DEFAULT_ICON_URL, "Permissions notification has the default icon");
disablePromise = promiseSetDisabled(mock2);
panel.button.click();
value = yield disablePromise;
is(value, false, "Addon should be set to enabled");
[addon1, addon2] = yield AddonManager.getAddonsByIDs([ID1, ID2]);
is(addon1.userDisabled, true, "Addon 1 should still be disabled");
is(addon2.userDisabled, false, "Addon 2 should now be enabled");
- yield BrowserTestUtils.removeTab(tab);
+ yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
--- a/browser/base/content/test/general/browser_extension_update.js
+++ b/browser/base/content/test/general/browser_extension_update.js
@@ -69,25 +69,36 @@ function promiseInstallEvent(addon, even
resolve(...args);
}
};
AddonManager.addInstallListener(listener);
});
}
// Set some prefs that apply to all the tests in this file
-add_task(function setup() {
- return SpecialPowers.pushPrefEnv({set: [
+add_task(function* setup() {
+ yield SpecialPowers.pushPrefEnv({set: [
// We don't have pre-pinned certificates for the local mochitest server
["extensions.install.requireBuiltInCerts", false],
["extensions.update.requireBuiltInCerts", false],
// XXX remove this when prompts are enabled by default
["extensions.webextPermissionPrompts", true],
]});
+
+ // Navigate away from the initial page so that about:addons always
+ // opens in a new tab during tests
+ gBrowser.selectedBrowser.loadURI("about:robots");
+ yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
+
+ registerCleanupFunction(function*() {
+ // Return to about:blank when we're done
+ gBrowser.selectedBrowser.loadURI("about:blank");
+ yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
+ });
});
// Helper function to test background updates.
function* backgroundUpdateTest(url, id, checkIconFn) {
yield SpecialPowers.pushPrefEnv({set: [
// Turn on background updates
["extensions.update.enabled", true],
@@ -118,17 +129,17 @@ function* backgroundUpdateTest(url, id,
// Click the menu item
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:addons");
let popupPromise = promisePopupNotificationShown("addon-webext-permissions");
addons.children[0].click();
// about:addons should load and go to the list of extensions
let tab = yield tabPromise;
- is(tab.linkedBrowser.currentURI.spec, "about:addons");
+ is(tab.linkedBrowser.currentURI.spec, "about:addons", "Browser is at about:addons");
const VIEW = "addons://list/extension";
yield promiseViewLoaded(tab, VIEW);
let win = tab.linkedBrowser.contentWindow;
ok(!win.gViewController.isLoading, "about:addons view is fully loaded");
is(win.gViewController.currentViewId, VIEW, "about:addons is at extensions list");
// Wait for the permission prompt, check the contents, then cancel the update
@@ -206,16 +217,59 @@ function checkNonDefaultIcon(icon) {
// inside the jar.
ok(icon.startsWith("jar:file://"), "Icon is a jar url");
ok(icon.endsWith("/icon.png"), "Icon is icon.png inside a jar");
}
add_task(() => backgroundUpdateTest(`${URL_BASE}/browser_webext_update_icon1.xpi`,
ID_ICON, checkNonDefaultIcon));
+// Test that an update that adds new non-promptable permissions is just
+// applied without showing a notification dialog.
+add_task(function*() {
+ yield SpecialPowers.pushPrefEnv({set: [
+ // Turn on background updates
+ ["extensions.update.enabled", true],
+
+ // Point updates to the local mochitest server
+ ["extensions.update.background.url", `${URL_BASE}/browser_webext_update.json`],
+ ]});
+
+ // Install version 1.0 of the test extension
+ let addon = yield promiseInstallAddon(`${URL_BASE}/browser_webext_update_perms1.xpi`);
+
+ ok(addon, "Addon was installed");
+
+ let sawPopup = false;
+ PopupNotifications.panel.addEventListener("popupshown",
+ () => sawPopup = true,
+ {once: true});
+
+ // Trigger an update check and wait for the update to be applied.
+ let updatePromise = promiseInstallEvent(addon, "onInstallEnded");
+ AddonManagerPrivate.backgroundUpdateCheck();
+ yield updatePromise;
+
+ // There should be no notifications about the update
+ is(getBadgeStatus(), "", "Should not have addon alert badge");
+
+ yield PanelUI.show();
+ let addons = document.getElementById("PanelUI-footer-addons");
+ is(addons.children.length, 0, "Have 0 updates in the PanelUI menu");
+ yield PanelUI.hide();
+
+ ok(!sawPopup, "Should not have seen permissions notification");
+
+ addon = yield AddonManager.getAddonByID("update_perms@tests.mozilla.org");
+ is(addon.version, "2.0", "Update should have applied");
+
+ addon.uninstall();
+ yield SpecialPowers.popPrefEnv();
+});
+
// Helper function to test a specific scenario for interactive updates.
// `checkFn` is a callable that triggers a check for updates.
// `autoUpdate` specifies whether the test should be run with
// updates applied automatically or not.
function* interactiveUpdateTest(autoUpdate, checkFn) {
yield SpecialPowers.pushPrefEnv({set: [
["extensions.update.autoUpdateDefault", autoUpdate],
--- a/browser/base/content/test/general/browser_webext_update.json
+++ b/browser/base/content/test/general/browser_webext_update.json
@@ -22,11 +22,25 @@
"applications": {
"gecko": {
"strict_min_version": "1",
"advisory_max_version": "55.0"
}
}
}
]
+ },
+ "update_perms@tests.mozilla.org": {
+ "updates": [
+ {
+ "version": "2.0",
+ "update_link": "https://example.com/browser/browser/base/content/test/general/browser_webext_update_perms2.xpi",
+ "applications": {
+ "gecko": {
+ "strict_min_version": "1",
+ "advisory_max_version": "55.0"
+ }
+ }
+ }
+ ]
}
}
}
new file mode 100644
index 0000000000000000000000000000000000000000..5887987844f5324fae82908b7ff66b524e01b747
GIT binary patch
literal 309
zc$^FHW@Zs#U|`^2a1D3&dZntcr4`6K3&gw(G7Pzid6{Xc#U*-K#rb)mA)E}%2PI}j
zfN*IAHv=QfS4IW~uy)^`(_Bo3Jg(pWc3s*kQu^}Le*sA+>Gp(pldG-H|L>N#UGaS|
zueexz>DJB(FWT-bQx97<=ZvR(xwA@##zB*bX{vHJL$z|V|90MAZFytw2F8U`9QfR3
zAJsY3a_+^upVF)o<n#L<EqoZV!OgBeahu_O4VDc%&!y>>@2tHoXPflTCw|?k)#d@-
rj7)OOxO^kQ00KY<Gc0KYvC#a+3h^77zXH5j*&x~&8G?cI8L%M$3!h}H
new file mode 100644
index 0000000000000000000000000000000000000000..71f613ca77c64128cb9fe2a29f5152ee4cf1f9eb
GIT binary patch
literal 317
zc$^FHW@Zs#U|`^2hzfW2>N@^jwHL^{3&gw(G7Pzid6{Xc#U*-K#rb)mA)E}%uO((h
zTms_K3T_5QmamKq3}EfPJ*T-2Iq<lC|JyaGRC0-T_`h}!&Rm^?m4=eB5x?I1Mg^KT
z&MAH$J8N5O!^HP0r4@mKeuC$6@6YUz@Q`1jm8dR!GQ#4z@>lh`&=+?-XF8s_`MG17
zm}$4sQsdtKFSVi{Qnseg+i+>ZN|v2BHtd*i?~U!QkhB|zSKs@3W1CEO&9e0ka$7m(
zo~>+(-fSiv;LXS+$BfHY5)2>!bU4G3Mi2|lkE{?sqWLeto0ScsjgcW3NM8XP0syBC
BYkvR$
--- a/browser/modules/ExtensionsUI.jsm
+++ b/browser/modules/ExtensionsUI.jsm
@@ -19,16 +19,19 @@ XPCOMUtils.defineLazyModuleGetter(this,
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyPreferenceGetter(this, "WEBEXT_PERMISSION_PROMPTS",
"extensions.webextPermissionPrompts", false);
const DEFAULT_EXTENSION_ICON = "chrome://mozapps/skin/extensions/extensionGeneric.svg";
+const BROWSER_PROPERTIES = "chrome://browser/locale/browser.properties";
+const BRAND_PROPERTIES = "chrome://browser/locale/brand.properties";
+
const HTML_NS = "http://www.w3.org/1999/xhtml";
this.ExtensionsUI = {
sideloaded: new Set(),
updates: new Set(),
init() {
Services.obs.addObserver(this, "webextension-permission-prompt", false);
@@ -60,65 +63,54 @@ this.ExtensionsUI = {
let win = RecentWindow.getMostRecentBrowserWindow();
for (let addon of sideloaded) {
win.openUILinkIn(`about:newaddon?id=${addon.id}`, "tab");
}
}
});
},
- showAddonsManager(browser, info) {
- let loadPromise = new Promise(resolve => {
- let listener = (subject, topic) => {
- if (subject.location.href == "about:addons") {
- Services.obs.removeObserver(listener, topic);
- resolve(subject);
- }
- };
- Services.obs.addObserver(listener, "EM-loaded", false);
- });
- let tab = browser.addTab("about:addons");
- browser.selectedTab = tab;
-
- return loadPromise.then(win => {
- win.loadView("addons://list/extension");
- return this.showPermissionsPrompt(browser.selectedBrowser, info);
+ showAddonsManager(browser, strings, icon) {
+ let global = browser.selectedBrowser.ownerGlobal;
+ return global.BrowserOpenAddonsMgr("addons://list/extension").then(aomWin => {
+ let aomBrowser = aomWin.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDocShell)
+ .chromeEventHandler;
+ return this.showPermissionsPrompt(aomBrowser, strings, icon);
});
},
showSideloaded(browser, addon) {
addon.markAsSeen();
this.sideloaded.delete(addon);
this.emit("change");
- let info = {
+ let strings = this._buildStrings({
addon,
permissions: addon.userPermissions,
- icon: addon.iconURL,
type: "sideload",
- };
- this.showAddonsManager(browser, info).then(answer => {
+ });
+ this.showAddonsManager(browser, strings, addon.iconURL).then(answer => {
addon.userDisabled = !answer;
});
},
showUpdate(browser, info) {
- info.icon = info.addon.iconURL;
- info.type = "update";
- this.showAddonsManager(browser, info).then(answer => {
- if (answer) {
- info.resolve();
- } else {
- info.reject();
- }
- // At the moment, this prompt will re-appear next time we do an update
- // check. See bug 1332360 for proposal to avoid this.
- this.updates.delete(info);
- this.emit("change");
- });
+ this.showAddonsManager(browser, info.strings, info.addon.iconURL)
+ .then(answer => {
+ if (answer) {
+ info.resolve();
+ } else {
+ info.reject();
+ }
+ // At the moment, this prompt will re-appear next time we do an update
+ // check. See bug 1332360 for proposal to avoid this.
+ this.updates.delete(info);
+ this.emit("change");
+ });
},
observe(subject, topic, data) {
if (topic == "webextension-permission-prompt") {
let {target, info} = subject.wrappedJSObject;
// Dismiss the progress notification. Note that this is bad if
// there are multiple simultaneous installs happening, see
@@ -136,20 +128,37 @@ this.ExtensionsUI = {
}
};
let perms = info.addon.userPermissions;
if (!perms) {
reply(true);
} else {
info.permissions = perms;
- this.showPermissionsPrompt(target, info).then(reply);
+ let strings = this._buildStrings(info);
+ this.showPermissionsPrompt(target, strings, info.icon).then(reply);
}
} else if (topic == "webextension-update-permissions") {
- this.updates.add(subject.wrappedJSObject);
+ let info = subject.wrappedJSObject;
+ let strings = this._buildStrings(info);
+
+ // If we don't prompt for any new permissions, just apply it
+ if (strings.msgs.length == 0) {
+ info.resolve();
+ return;
+ }
+
+ let update = {
+ strings,
+ addon: info.addon,
+ resolve: info.resolve,
+ reject: info.reject,
+ };
+
+ this.updates.add(update);
this.emit("change");
} else if (topic == "webextension-install-notify") {
let {target, addon, callback} = subject.wrappedJSObject;
this.showInstallNotification(target, addon).then(() => {
if (callback) {
callback();
}
});
@@ -159,66 +168,64 @@ this.ExtensionsUI = {
// Escape &, <, and > characters in a string so that it may be
// injected as part of raw markup.
_sanitizeName(name) {
return name.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">");
},
- showPermissionsPrompt(target, info) {
- let perms = info.permissions;
- if (!perms) {
- return Promise.resolve();
- }
+ // Create a set of formatted strings for a permission prompt
+ _buildStrings(info) {
+ let result = {};
- let win = target.ownerGlobal;
+ let bundle = Services.strings.createBundle(BROWSER_PROPERTIES);
let name = info.addon.name;
if (name.length > 50) {
name = name.slice(0, 49) + "…";
}
name = this._sanitizeName(name);
-
let addonName = `<span class="addon-webext-name">${name}</span>`;
- let bundle = win.gNavigatorBundle;
- let header = bundle.getFormattedString("webextPerms.header", [addonName]);
- let text = "";
- let listIntro = bundle.getString("webextPerms.listIntro");
+ result.header = bundle.formatStringFromName("webextPerms.header", [addonName], 1);
+ result.text = "";
+ result.listIntro = bundle.GetStringFromName("webextPerms.listIntro");
- let acceptText = bundle.getString("webextPerms.add.label");
- let acceptKey = bundle.getString("webextPerms.add.accessKey");
- let cancelText = bundle.getString("webextPerms.cancel.label");
- let cancelKey = bundle.getString("webextPerms.cancel.accessKey");
+ result.acceptText = bundle.GetStringFromName("webextPerms.add.label");
+ result.acceptKey = bundle.GetStringFromName("webextPerms.add.accessKey");
+ result.cancelText = bundle.GetStringFromName("webextPerms.cancel.label");
+ result.cancelKey = bundle.GetStringFromName("webextPerms.cancel.accessKey");
if (info.type == "sideload") {
- header = bundle.getFormattedString("webextPerms.sideloadHeader", [addonName]);
- text = bundle.getString("webextPerms.sideloadText");
- acceptText = bundle.getString("webextPerms.sideloadEnable.label");
- acceptKey = bundle.getString("webextPerms.sideloadEnable.accessKey");
- cancelText = bundle.getString("webextPerms.sideloadDisable.label");
- cancelKey = bundle.getString("webextPerms.sideloadDisable.accessKey");
+ result.header = bundle.formatStringFromName("webextPerms.sideloadHeader", [addonName], 1);
+ result.text = bundle.GetStringFromName("webextPerms.sideloadText");
+ result.acceptText = bundle.GetStringFromName("webextPerms.sideloadEnable.label");
+ result.acceptKey = bundle.GetStringFromName("webextPerms.sideloadEnable.accessKey");
+ result.cancelText = bundle.GetStringFromName("webextPerms.sideloadDisable.label");
+ result.cancelKey = bundle.GetStringFromName("webextPerms.sideloadDisable.accessKey");
} else if (info.type == "update") {
- header = "";
- text = bundle.getFormattedString("webextPerms.updateText", [addonName]);
- acceptText = bundle.getString("webextPerms.updateAccept.label");
- acceptKey = bundle.getString("webextPerms.updateAccept.accessKey");
+ result.header = "";
+ result.text = bundle.formatStringFromName("webextPerms.updateText", [addonName], 1);
+ result.acceptText = bundle.GetStringFromName("webextPerms.updateAccept.label");
+ result.acceptKey = bundle.GetStringFromName("webextPerms.updateAccept.accessKey");
}
- let msgs = [];
+ let perms = info.permissions || {hosts: [], permissions: []};
+
+ result.msgs = [];
for (let permission of perms.permissions) {
let key = `webextPerms.description.${permission}`;
if (permission == "nativeMessaging") {
- let brandBundle = win.document.getElementById("bundle_brand");
- let appName = brandBundle.getString("brandShortName");
- msgs.push(bundle.getFormattedString(key, [appName]));
+ let brandBundle = Services.strings.createBundle(BRAND_PROPERTIES);
+ let appName = brandBundle.GetStringFromName("brandShortName");
+ result.msgs.push(bundle.formatStringFromName(key, [appName], 1));
} else {
try {
- msgs.push(bundle.getString(key));
+ result.msgs.push(bundle.GetStringFromName(key));
} catch (err) {
// We deliberately do not include all permissions in the prompt.
// So if we don't find one then just skip it.
}
}
}
let allUrls = false, wildcards = [], sites = [];
@@ -236,92 +243,100 @@ this.ExtensionsUI = {
} else if (match[1].startsWith("*.")) {
wildcards.push(match[1].slice(2));
} else {
sites.push(match[1]);
}
}
if (allUrls) {
- msgs.push(bundle.getString("webextPerms.hostDescription.allUrls"));
+ result.msgs.push(bundle.GetStringFromName("webextPerms.hostDescription.allUrls"));
} else {
// Formats a list of host permissions. If we have 4 or fewer, display
// them all, otherwise display the first 3 followed by an item that
// says "...plus N others"
function format(list, itemKey, moreKey) {
function formatItems(items) {
- msgs.push(...items.map(item => bundle.getFormattedString(itemKey, [item])));
+ result.msgs.push(...items.map(item => bundle.formatStringFromName(itemKey, [item], 1)));
}
if (list.length < 5) {
formatItems(list);
} else {
formatItems(list.slice(0, 3));
let remaining = list.length - 3;
- msgs.push(PluralForm.get(remaining, bundle.getString(moreKey))
- .replace("#1", remaining));
+ result.msgs.push(PluralForm.get(remaining, bundle.GetStringFromName(moreKey))
+ .replace("#1", remaining));
}
}
format(wildcards, "webextPerms.hostDescription.wildcard",
"webextPerms.hostDescription.tooManyWildcards");
format(sites, "webextPerms.hostDescription.oneSite",
"webextPerms.hostDescription.tooManySites");
}
+ return result;
+ },
+
+ showPermissionsPrompt(browser, strings, icon) {
+ function eventCallback(topic) {
+ if (topic == "showing") {
+ let doc = this.browser.ownerDocument;
+ doc.getElementById("addon-webext-perm-header").innerHTML = strings.header;
+
+ let textEl = doc.getElementById("addon-webext-perm-text");
+ textEl.innerHTML = strings.text;
+ textEl.hidden = !strings.text;
+
+ let listIntroEl = doc.getElementById("addon-webext-perm-intro");
+ listIntroEl.value = strings.listIntro;
+ listIntroEl.hidden = (strings.msgs.length == 0);
+
+ let list = doc.getElementById("addon-webext-perm-list");
+ while (list.firstChild) {
+ list.firstChild.remove();
+ }
+
+ for (let msg of strings.msgs) {
+ let item = doc.createElementNS(HTML_NS, "li");
+ item.textContent = msg;
+ list.appendChild(item);
+ }
+ } else if (topic == "swapping") {
+ return true;
+ }
+ return false;
+ }
+
let popupOptions = {
hideClose: true,
- popupIconURL: info.icon || DEFAULT_EXTENSION_ICON,
+ popupIconURL: icon || DEFAULT_EXTENSION_ICON,
persistent: true,
-
- eventCallback(topic) {
- if (topic == "showing") {
- let doc = this.browser.ownerDocument;
- doc.getElementById("addon-webext-perm-header").innerHTML = header;
-
- let textEl = doc.getElementById("addon-webext-perm-text");
- textEl.innerHTML = text;
- textEl.hidden = !text;
-
- let listIntroEl = doc.getElementById("addon-webext-perm-intro");
- listIntroEl.value = listIntro;
- listIntroEl.hidden = (msgs.length == 0);
-
- let list = doc.getElementById("addon-webext-perm-list");
- while (list.firstChild) {
- list.firstChild.remove();
- }
-
- for (let msg of msgs) {
- let item = doc.createElementNS(HTML_NS, "li");
- item.textContent = msg;
- list.appendChild(item);
- }
- } else if (topic == "swapping") {
- return true;
- }
- return false;
- },
+ eventCallback,
};
+ let win = browser.ownerGlobal;
return new Promise(resolve => {
- win.PopupNotifications.show(target, "addon-webext-permissions", "",
+ let action = {
+ label: strings.acceptText,
+ accessKey: strings.acceptKey,
+ callback: () => resolve(true),
+ };
+ let secondaryActions = [
+ {
+ label: strings.cancelText,
+ accessKey: strings.cancelKey,
+ callback: () => resolve(false),
+ },
+ ];
+
+ win.PopupNotifications.show(browser, "addon-webext-permissions", "",
"addons-notification-icon",
- {
- label: acceptText,
- accessKey: acceptKey,
- callback: () => resolve(true),
- },
- [
- {
- label: cancelText,
- accessKey: cancelKey,
- callback: () => resolve(false),
- },
- ], popupOptions);
+ action, secondaryActions, popupOptions);
});
},
showInstallNotification(target, addon) {
let win = target.ownerGlobal;
let popups = win.PopupNotifications;
let name = this._sanitizeName(addon.name);