Bug 1316996 Text for webextensions permissions
MozReview-Commit-ID: 3W7zEemDOTa
--- a/browser/base/content/browser-addons.js
+++ b/browser/base/content/browser-addons.js
@@ -498,43 +498,51 @@ const gExtensionsNotifications = {
}
let container = document.getElementById("PanelUI-footer-addons");
while (container.firstChild) {
container.firstChild.remove();
}
- // Strings below to be properly localized in bug 1316996
const DEFAULT_EXTENSION_ICON =
"chrome://mozapps/skin/extensions/extensionGeneric.svg";
let items = 0;
for (let update of updates) {
if (++items > 4) {
break;
}
+
let button = document.createElement("toolbarbutton");
- button.setAttribute("label", `"${update.addon.name}" requires new permissions`);
+ let text = gNavigatorBundle.getFormattedString("webextPerms.updateMenuItem", [update.addon.name]);
+ button.setAttribute("label", text);
let icon = update.addon.iconURL || DEFAULT_EXTENSION_ICON;
button.setAttribute("image", icon);
button.addEventListener("click", evt => {
ExtensionsUI.showUpdate(gBrowser, update);
});
container.appendChild(button);
}
+ let appName;
for (let addon of sideloaded) {
if (++items > 4) {
break;
}
+ if (!appName) {
+ let brandBundle = document.getElementById("bundle_brand");
+ appName = brandBundle.getString("brandShortName");
+ }
+
let button = document.createElement("toolbarbutton");
- button.setAttribute("label", `"${addon.name}" added to Firefox`);
+ let text = gNavigatorBundle.getFormattedString("webextPerms.sideloadMenuItem", [addon.name, appName]);
+ button.setAttribute("label", text);
let icon = addon.iconURL || DEFAULT_EXTENSION_ICON;
button.setAttribute("image", icon);
button.addEventListener("click", evt => {
ExtensionsUI.showSideloaded(gBrowser, addon);
});
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -28,16 +28,103 @@ xpinstallPromptAllowButton=Allow
# Be sure you do not choose an accesskey that is used elsewhere in the active context (e.g. main menu bar, submenu of the warning popup button)
# See http://www.mozilla.org/access/keyboard/accesskey for details
xpinstallPromptAllowButton.accesskey=A
xpinstallDisabledMessageLocked=Software installation has been disabled by your system administrator.
xpinstallDisabledMessage=Software installation is currently disabled. Click Enable and try again.
xpinstallDisabledButton=Enable
xpinstallDisabledButton.accesskey=n
+# LOCALIZATION NOTE (webextPerms.header)
+# This string is used as a header in the webextension permissions dialog,
+# %S is replaced with the localized name of the extension being installed.
+# See https://bug1308309.bmoattachments.org/attachment.cgi?id=8814612
+# for an example of the full dialog.
+# Note, this string will be used as raw markup. Avoid characters like <, >, &
+webextPerms.header=Add %S?
+
+# LOCALIZATION NOTE (webextPerms.listIntro)
+# This string will be followed by a list of permissions requested
+# by the webextension.
+webextPerms.listIntro=It requires your permission to:
+webextPerms.add.label=Add
+webextPerms.add.accessKey=A
+webextPerms.cancel.label=Cancel
+webextPerms.cancel.accessKey=C
+
+# LOCALIZATION NOTE (webextPerms.sideloadMenuItem)
+# %1$S will be replaced with the localized name of the sideloaded add-on.
+# %2$S will be replace with the name of the application (e.g., Firefox, Nightly)
+webextPerms.sideloadMenuItem=%1$S added to %2$S
+
+# LOCALIZATION NOTE (webextPerms.sideloadHeader)
+# This string is used as a header in the webextension permissions dialog
+# when the extension is side-loaded.
+# %S is replaced with the localized name of the extension being installed.
+# Note, this string will be used as raw markup. Avoid characters like <, >, &
+webextPerms.sideloadHeader=%S added
+webextPerms.sideloadText=Another program on your computer installed an add-on that may affect your browser. Please review this add-on’s permissions requests and choose to Enable or Disable.
+
+webextPerms.sideloadEnable.label=Enable
+webextPerms.sideloadEnable.accessKey=E
+webextPerms.sideloadDisable.label=Disable
+webextPerms.sideloadDisable.accessKey=D
+
+# LOCALIZATION NOTE (webextPerms.updateMenuItem)
+# %S will be replaced with the localized name of the extension which
+# has been updated.
+webextPerms.updateMenuItem=%S requires new permissions
+
+# LOCALIZATION NOTE (webextPerms.updateText)
+# %S is replaced with the localized name of the updated extension.
+# Note, this string will be used as raw markup. Avoid characters like <, >, &
+webextPerms.updateText=%S has been updated. You must approve new permissions before the updated version will install. Choosing “Cancel” will maintain your current add-on version.
+
+webextPerms.updateAccept.label=Update
+webextPerms.updateAccept.accessKey=U
+
+webextPerms.description.bookmarks=Read and modify bookmarks
+webextPerms.description.downloads=Download files and read and modify the browser’s download history
+webextPerms.description.history=Access browsing history
+# LOCALIZATION NOTE (webextPerms.description.nativeMessaging)
+# %S will be replaced with the name of the application
+webextPerms.description.nativeMessaging=Exchange messages with programs other than %S
+webextPerms.description.notifications=Display notifications to you
+webextPerms.description.sessions=Access browser recently closed tabs
+webextPerms.description.tabs=Access browser tabs
+webextPerms.description.topSites=Access browsing history
+webextPerms.description.webNavigation=Access browser activity during navigation
+
+webextPerms.hostDescription.allUrls=Access your data for all websites
+
+# LOCALIZATION NOTE (webextPerms.hostDescription.wildcard)
+# %S will be replaced by the DNS domain for which a webextension
+# is requesting access (e.g., mozilla.org)
+webextPerms.hostDescription.wildcard=Access your data for sites in the %S domain
+
+# LOCALIZATION NOTE (webextPerms.hostDescription.tooManyWildcards):
+# Semi-colon list of plural forms.
+# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
+# #1 will be replaced by an integer indicating the number of additional
+# domains for which this webextension is requesting permission.
+webextPerms.hostDescription.tooManyWildcards=Access your data in #1 other domain;Access your data in #1 other domains
+
+# LOCALIZATION NOTE (webextPerms.hostDescription.oneSite)
+# %S will be replaced by the DNS host name for which a webextension
+# is requesting access (e.g., www.mozilla.org)
+webextPerms.hostDescription.oneSite=Access your data for %S
+
+# LOCALIZATION NOTE (webextPerms.hostDescription.tooManySites)
+# Semi-colon list of plural forms.
+# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
+# #1 will be replaced by an integer indicating the number of additional
+# hosts for which this webextension is requesting permission.
+webextPerms.hostDescription.tooManySites=Access your data on #1 other site;Access your data on #1 other sites
+
+
# LOCALIZATION NOTE (addonDownloadingAndVerifying):
# Semicolon-separated list of plural forms. See:
# http://developer.mozilla.org/en/docs/Localization_and_Plurals
# Also see https://bugzilla.mozilla.org/show_bug.cgi?id=570012 for mockups
addonDownloadingAndVerifying=Downloading and verifying add-on…;Downloading and verifying #1 add-ons…
addonDownloadVerifying=Verifying
addonInstall.unsigned=(Unverified)
--- a/browser/modules/ExtensionsUI.jsm
+++ b/browser/modules/ExtensionsUI.jsm
@@ -7,16 +7,18 @@ const {classes: Cc, interfaces: Ci, resu
this.EXPORTED_SYMBOLS = ["ExtensionsUI"];
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://devtools/shared/event-emitter.js");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
+ "resource://gre/modules/PluralForm.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
"resource:///modules/RecentWindow.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyPreferenceGetter(this, "WEBEXT_PERMISSION_PROMPTS",
"extensions.webextPermissionPrompts", false);
@@ -149,114 +151,138 @@ this.ExtensionsUI = {
}
let win = target.ownerGlobal;
let name = info.addon.name;
if (name.length > 50) {
name = name.slice(0, 49) + "…";
}
-
- // The strings below are placeholders, they will switch over to the
- // bundle.get*String() calls as part of bug 1316996.
+ name = name.replace(/&/g, "&")
+ .replace(/</g, "<")
+ .replace(/>/g, ">");
- // let bundle = win.gNavigatorBundle;
- // let header = bundle.getFormattedString("webextPerms.header", [name])
- // let listHeader = bundle.getString("webextPerms.listHeader");
- let header = "Add ADDON?".replace("ADDON", name);
+ let addonLabel = `<label class="addon-webext-name">${name}</label>`;
+ let bundle = win.gNavigatorBundle;
+
+ let header = bundle.getFormattedString("webextPerms.header", [addonLabel]);
let text = "";
- let listHeader = "It can:";
+ let listIntro = bundle.getString("webextPerms.listIntro");
- // let acceptText = bundle.getString("webextPerms.accept.label");
- // let acceptKey = bundle.getString("webextPerms.accept.accessKey");
- // let cancelText = bundle.getString("webextPerms.cancel.label");
- // let cancelKey = bundle.getString("webextPerms.cancel.accessKey");
- let acceptText = "Add extension";
- let acceptKey = "A";
- let cancelText = "Cancel";
- let cancelKey = "C";
+ 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");
if (info.type == "sideload") {
- header = `${name} added`;
- text = "Another program on your computer installed an add-on that may affect your browser. Please review this add-on's permission requests and choose to Enable or Disable";
- acceptText = "Enable";
- acceptKey = "E";
- cancelText = "Disable";
- cancelKey = "D";
+ header = bundle.getFormattedString("webextPerms.sideloadHeader", [addonLabel]);
+ 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");
} else if (info.type == "update") {
header = "";
- text = `${name} has been updated. You must approve new permissions before the updated version will install.`;
- acceptText = "Update";
- acceptKey = "U";
+ text = bundle.getFormattedString("webextPerms.updateText", [addonLabel]);
+ acceptText = bundle.getString("webextPerms.updateAccept.label");
+ acceptKey = bundle.getString("webextPerms.updateAccept.accessKey");
}
- let formatPermission = perm => {
- try {
- // return bundle.getString(`webextPerms.description.${perm}`);
- return `localized description of permission ${perm}`;
- } catch (err) {
- // return bundle.getFormattedString("webextPerms.description.unknown",
- // [perm]);
- return `localized description of unknown permission ${perm}`;
+ let 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]));
+ } else {
+ try {
+ msgs.push(bundle.getString(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 formatHostPermission = perm => {
- if (perm == "<all_urls>") {
- // return bundle.getString("webextPerms.hostDescription.allUrls");
- return "localized description of <all_urls> host permission";
+ let allUrls = false, wildcards = [], sites = [];
+ for (let permission of perms.hosts) {
+ if (permission == "<all_urls>") {
+ allUrls = true;
+ break;
}
- let match = /^[htps*]+:\/\/([^/]+)\//.exec(perm);
+ let match = /^[htps*]+:\/\/([^/]+)\//.exec(permission);
if (!match) {
throw new Error("Unparseable host permission");
}
- if (match[1].startsWith("*.")) {
- let domain = match[1].slice(2);
- // return bundle.getFormattedString("webextPerms.hostDescription.wildcard", [domain]);
- return `localized description of wildcard host permission for ${domain}`;
+ if (match[1] == "*") {
+ allUrls = true;
+ } 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"));
+ } 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])));
+ }
+ 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));
+ }
}
- // return bundle.getFormattedString("webextPerms.hostDescription.oneSite", [match[1]]);
- return `localized description of single host permission for ${match[1]}`;
- };
-
- let msgs = [
- ...perms.permissions.map(formatPermission),
- ...perms.hosts.map(formatHostPermission),
- ];
+ format(wildcards, "webextPerms.hostDescription.wildcard",
+ "webextPerms.hostDescription.tooManyWildcards");
+ format(sites, "webextPerms.hostDescription.oneSite",
+ "webextPerms.hostDescription.tooManySites");
+ }
let rendered = false;
let popupOptions = {
hideClose: true,
popupIconURL: info.icon,
persistent: true,
eventCallback(topic) {
if (topic == "showing") {
// This check can be removed when bug 1325223 is resolved.
if (rendered) {
return false;
}
let doc = this.browser.ownerDocument;
- doc.getElementById("addon-webext-perm-header").textContent = header;
+ doc.getElementById("addon-webext-perm-header").innerHTML = header;
+
+ if (text) {
+ doc.getElementById("addon-webext-perm-text").innerHTML = 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();
}
- if (text) {
- doc.getElementById("addon-webext-perm-text").textContent = text;
- }
-
- let listHeaderEl = doc.getElementById("addon-webext-perm-intro");
- listHeaderEl.value = listHeader;
- listHeaderEl.hidden = (msgs.length == 0);
-
for (let msg of msgs) {
let item = doc.createElementNS(HTML_NS, "li");
item.textContent = msg;
list.appendChild(item);
}
rendered = true;
} else if (topic == "dismissed") {
rendered = false;
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -829,18 +829,22 @@ menuitem.bookmark-item {
max-width: 28em;
}
.addon-install-confirmation-name {
font-weight: bold;
}
.addon-webext-perm-header {
+ font-size: 1.3em;
+}
+
+.addon-webext-name {
font-weight: bold;
- font-size: 1.3em;
+ margin: 0;
}
/* Notification icon box */
.notification-anchor-icon:-moz-focusring {
outline: 1px dotted -moz-DialogText;
}
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -3087,18 +3087,22 @@ menulist.translate-infobar-element > .me
max-width: 28em;
}
.addon-install-confirmation-name {
font-weight: bold;
}
.addon-webext-perm-header {
+ font-size: 1.3em;
+}
+
+.addon-webext-name {
font-weight: bold;
- font-size: 1.3em;
+ margin: 0;
}
/* Status panel */
.statuspanel-label {
margin: 0;
padding: 2px 4px;
background: linear-gradient(#fff, #ddd);
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2132,18 +2132,22 @@ toolbarbutton.bookmark-item[dragover="tr
max-width: 28em;
}
.addon-install-confirmation-name {
font-weight: bold;
}
.addon-webext-perm-header {
+ font-size: 1.3em;
+}
+
+.addon-webext-name {
font-weight: bold;
- font-size: 1.3em;
+ margin: 0;
}
/* Notification icon box */
.notification-anchor-icon:-moz-focusring {
outline: 1px dotted -moz-DialogText;
}