diff --git a/browser/modules/ExtensionsUI.jsm b/browser/modules/ExtensionsUI.jsm
index e51999c472de..1928f33cf333 100644
--- a/browser/modules/ExtensionsUI.jsm
+++ b/browser/modules/ExtensionsUI.jsm
@@ -16,8 +16,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "AddonManagerPrivate",
"resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AppMenuNotifications",
"resource://gre/modules/AppMenuNotifications.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
- "resource://gre/modules/PluralForm.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "ExtensionData",
+ "resource://gre/modules/Extension.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
"resource:///modules/RecentWindow.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
@@ -252,127 +252,15 @@ this.ExtensionsUI = {
// Create a set of formatted strings for a permission prompt
_buildStrings(info) {
- let result = {};
-
let bundle = Services.strings.createBundle(BROWSER_PROPERTIES);
- let perms = info.permissions || {origins: [], permissions: []};
+ let brandBundle = Services.strings.createBundle(BRAND_PROPERTIES);
+ let appName = brandBundle.GetStringFromName("brandShortName");
+ let addonName = `${this._sanitizeName(info.addon.name)}`;
- // First classify our host permissions
- let allUrls = false, wildcards = [], sites = [];
- for (let permission of perms.origins) {
- if (permission == "") {
- allUrls = true;
- break;
- }
- let match = /^[htps*]+:\/\/([^/]+)\//.exec(permission);
- if (!match) {
- Cu.reportError(`Unparseable host permission ${permission}`);
- continue;
- }
- if (match[1] == "*") {
- allUrls = true;
- } else if (match[1].startsWith("*.")) {
- wildcards.push(match[1].slice(2));
- } else {
- sites.push(match[1]);
- }
- }
+ let info2 = Object.assign({appName, addonName}, info);
- // Format the host permissions. If we have a wildcard for all urls,
- // a single string will suffice. Otherwise, show domain wildcards
- // first, then individual host permissions.
- result.msgs = [];
- if (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) {
- 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;
- 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");
- }
-
- let permissionKey = perm => `webextPerms.description.${perm}`;
-
- // Next, show the native messaging permission if it is present.
- const NATIVE_MSG_PERM = "nativeMessaging";
- if (perms.permissions.includes(NATIVE_MSG_PERM)) {
- let brandBundle = Services.strings.createBundle(BRAND_PROPERTIES);
- let appName = brandBundle.GetStringFromName("brandShortName");
- result.msgs.push(bundle.formatStringFromName(permissionKey(NATIVE_MSG_PERM), [appName], 1));
- }
-
- // Finally, show remaining permissions, in any order.
- for (let permission of perms.permissions) {
- // Handled above
- if (permission == "nativeMessaging") {
- continue;
- }
- try {
- result.msgs.push(bundle.GetStringFromName(permissionKey(permission)));
- } catch (err) {
- // We deliberately do not include all permissions in the prompt.
- // So if we don't find one then just skip it.
- }
- }
-
- // Now figure out all the rest of the notification text.
- let name = this._sanitizeName(info.addon.name);
- let addonName = `${name}`;
-
- result.header = bundle.formatStringFromName("webextPerms.header", [addonName], 1);
- result.text = info.unsigned ?
- bundle.GetStringFromName("webextPerms.unsignedWarning") : "";
- result.listIntro = bundle.GetStringFromName("webextPerms.listIntro");
-
- 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") {
- result.header = bundle.formatStringFromName("webextPerms.sideloadHeader", [addonName], 1);
- let key = result.msgs.length == 0 ?
- "webextPerms.sideloadTextNoPerms" : "webextPerms.sideloadText2";
- result.text = bundle.GetStringFromName(key);
- result.acceptText = bundle.GetStringFromName("webextPerms.sideloadEnable.label");
- result.acceptKey = bundle.GetStringFromName("webextPerms.sideloadEnable.accessKey");
- result.cancelText = bundle.GetStringFromName("webextPerms.sideloadCancel.label");
- result.cancelKey = bundle.GetStringFromName("webextPerms.sideloadCancel.accessKey");
- } else if (info.type == "update") {
- result.header = "";
- result.text = bundle.formatStringFromName("webextPerms.updateText", [addonName], 1);
- result.acceptText = bundle.GetStringFromName("webextPerms.updateAccept.label");
- result.acceptKey = bundle.GetStringFromName("webextPerms.updateAccept.accessKey");
- } else if (info.type == "optional") {
- result.header = bundle.formatStringFromName("webextPerms.optionalPermsHeader", [addonName], 1);
- result.text = "";
- result.listIntro = bundle.GetStringFromName("webextPerms.optionalPermsListIntro");
- result.acceptText = bundle.GetStringFromName("webextPerms.optionalPermsAllow.label");
- result.acceptKey = bundle.GetStringFromName("webextPerms.optionalPermsAllow.accessKey");
- result.cancelText = bundle.GetStringFromName("webextPerms.optionalPermsDeny.label");
- result.cancelKey = bundle.GetStringFromName("webextPerms.optionalPermsDeny.accessKey");
- }
-
- return result;
+ return ExtensionData.formatPermissionStrings(info2, bundle);
},
showPermissionsPrompt(browser, strings, icon, histkey) {
diff --git a/toolkit/components/extensions/Extension.jsm b/toolkit/components/extensions/Extension.jsm
index d838d880141d..7505daae9024 100644
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -57,6 +57,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
MessageChannel: "resource://gre/modules/MessageChannel.jsm",
NetUtil: "resource://gre/modules/NetUtil.jsm",
OS: "resource://gre/modules/osfile.jsm",
+ PluralForm: "resource://gre/modules/PluralForm.jsm",
Schemas: "resource://gre/modules/Schemas.jsm",
setTimeout: "resource://gre/modules/Timer.jsm",
TelemetryStopwatch: "resource://gre/modules/TelemetryStopwatch.jsm",
@@ -790,6 +791,149 @@ this.ExtensionData = class {
this.localeData.selectedLocale = locale;
return results[0];
}
+
+ /**
+ * Formats all the strings for a permissions dialog/notification.
+ *
+ * @param {object} info Information about the permissions being requested.
+ *
+ * @param {array} info.permissions.origins
+ * Origin permissions requested.
+ * @param {array} info.permissions.permissions
+ * Regular (non-origin) permissions requested.
+ * @param {AddonWrapper} info.addonName
+ * The name of the addon for which permissions are
+ * being requested.
+ * @param {boolean} info.unsigned
+ * True if the prompt is for installing an unsigned addon.
+ * @param {string} info.type
+ * The type of prompt being shown. May be one of "update",
+ * "sideload", "optional", or omitted for a regular
+ * install prompt.
+ * @param {string} info.appName
+ * The localized name of the application, to be substituted
+ * in computed strings as needed.
+ * @param {nsIStringBundle} bundle
+ * The string bundle to use for l10n.
+ *
+ * @returns {object} An object with properties containing localized strings
+ * for various elements of a permission dialog.
+ */
+ static formatPermissionStrings(info, bundle) {
+ let result = {};
+
+ let perms = info.permissions || {origins: [], permissions: []};
+
+ // First classify our host permissions
+ let allUrls = false, wildcards = [], sites = [];
+ for (let permission of perms.origins) {
+ if (permission == "") {
+ allUrls = true;
+ break;
+ }
+ let match = /^[htps*]+:\/\/([^/]+)\//.exec(permission);
+ if (!match) {
+ Cu.reportError(`Unparseable host permission ${permission}`);
+ continue;
+ }
+ if (match[1] == "*") {
+ allUrls = true;
+ } else if (match[1].startsWith("*.")) {
+ wildcards.push(match[1].slice(2));
+ } else {
+ sites.push(match[1]);
+ }
+ }
+
+ // Format the host permissions. If we have a wildcard for all urls,
+ // a single string will suffice. Otherwise, show domain wildcards
+ // first, then individual host permissions.
+ result.msgs = [];
+ if (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"
+ let format = (list, itemKey, moreKey) => {
+ function formatItems(items) {
+ 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;
+ 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");
+ }
+
+ let permissionKey = perm => `webextPerms.description.${perm}`;
+
+ // Next, show the native messaging permission if it is present.
+ const NATIVE_MSG_PERM = "nativeMessaging";
+ if (perms.permissions.includes(NATIVE_MSG_PERM)) {
+ result.msgs.push(bundle.formatStringFromName(permissionKey(NATIVE_MSG_PERM), [info.appName], 1));
+ }
+
+ // Finally, show remaining permissions, in any order.
+ for (let permission of perms.permissions) {
+ // Handled above
+ if (permission == "nativeMessaging") {
+ continue;
+ }
+ try {
+ result.msgs.push(bundle.GetStringFromName(permissionKey(permission)));
+ } catch (err) {
+ // We deliberately do not include all permissions in the prompt.
+ // So if we don't find one then just skip it.
+ }
+ }
+
+ result.header = bundle.formatStringFromName("webextPerms.header", [info.addonName], 1);
+ result.text = info.unsigned ?
+ bundle.GetStringFromName("webextPerms.unsignedWarning") : "";
+ result.listIntro = bundle.GetStringFromName("webextPerms.listIntro");
+
+ 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") {
+ result.header = bundle.formatStringFromName("webextPerms.sideloadHeader", [info.addonName], 1);
+ let key = result.msgs.length == 0 ?
+ "webextPerms.sideloadTextNoPerms" : "webextPerms.sideloadText2";
+ result.text = bundle.GetStringFromName(key);
+ result.acceptText = bundle.GetStringFromName("webextPerms.sideloadEnable.label");
+ result.acceptKey = bundle.GetStringFromName("webextPerms.sideloadEnable.accessKey");
+ result.cancelText = bundle.GetStringFromName("webextPerms.sideloadCancel.label");
+ result.cancelKey = bundle.GetStringFromName("webextPerms.sideloadCancel.accessKey");
+ } else if (info.type == "update") {
+ result.header = "";
+ result.text = bundle.formatStringFromName("webextPerms.updateText", [info.addonName], 1);
+ result.acceptText = bundle.GetStringFromName("webextPerms.updateAccept.label");
+ result.acceptKey = bundle.GetStringFromName("webextPerms.updateAccept.accessKey");
+ } else if (info.type == "optional") {
+ result.header = bundle.formatStringFromName("webextPerms.optionalPermsHeader", [info.addonName], 1);
+ result.text = "";
+ result.listIntro = bundle.GetStringFromName("webextPerms.optionalPermsListIntro");
+ result.acceptText = bundle.GetStringFromName("webextPerms.optionalPermsAllow.label");
+ result.acceptKey = bundle.GetStringFromName("webextPerms.optionalPermsAllow.accessKey");
+ result.cancelText = bundle.GetStringFromName("webextPerms.optionalPermsDeny.label");
+ result.cancelKey = bundle.GetStringFromName("webextPerms.optionalPermsDeny.accessKey");
+ }
+
+ return result;
+ }
};
const PROXIED_EVENTS = new Set(["test-harness-message", "add-permissions", "remove-permissions"]);