Bug 1431242 - Use popupnotification's built-in bolding for webextension prompts. r?johannh,aswan
MozReview-Commit-ID: 52AtWUlJj4p
--- a/browser/base/content/browser-addons.js
+++ b/browser/base/content/browser-addons.js
@@ -640,17 +640,18 @@ var LightWeightThemeWebInstaller = {
}
if (this._isAllowed(baseURI)) {
this._install(data, notify);
return;
}
let strings = {
- header: gNavigatorBundle.getFormattedString("webextPerms.header", [data.name]),
+ header: gNavigatorBundle.getFormattedString("webextPerms.header", ["<>"]),
+ addonName: data.name,
text: gNavigatorBundle.getFormattedString("lwthemeInstallRequest.message2",
[uri.host]),
acceptText: gNavigatorBundle.getString("lwthemeInstallRequest.allowButton2"),
acceptKey: gNavigatorBundle.getString("lwthemeInstallRequest.allowButton.accesskey2"),
cancelText: gNavigatorBundle.getString("webextPerms.cancel.label"),
cancelKey: gNavigatorBundle.getString("webextPerms.cancel.accessKey"),
msgs: []
};
--- a/browser/base/content/popup-notifications.inc
+++ b/browser/base/content/popup-notifications.inc
@@ -69,27 +69,19 @@
</popupnotification>
<popupnotification id="addon-install-confirmation-notification" hidden="true">
<popupnotificationcontent id="addon-install-confirmation-content" orient="vertical"/>
</popupnotification>
<popupnotification id="addon-webext-permissions-notification" hidden="true">
<popupnotificationcontent class="addon-webext-perm-notification-content" orient="vertical">
- <description id="addon-webext-perm-header" class="addon-webext-perm-header"/>
<description id="addon-webext-perm-text" class="addon-webext-perm-text"/>
<label id="addon-webext-perm-intro" class="addon-webext-perm-text"/>
<html:ul id="addon-webext-perm-list" class="addon-webext-perm-list"/>
</popupnotificationcontent>
</popupnotification>
- <popupnotification id="addon-webext-defaultsearch-notification" hidden="true">
- <popupnotificationcontent class="addon-webext-defaultsearch-notification-content" orient="vertical">
- <description id="addon-webext-defaultsearch-text" class="addon-webext-perm-header"/>
- </popupnotificationcontent>
- </popupnotification>
-
<popupnotification id="addon-installed-notification" hidden="true">
<popupnotificationcontent class="addon-installed-notification-content" orient="vertical">
- <description id="addon-installed-notification-header"/>
<description id="addon-installed-notification-message"/>
</popupnotificationcontent>
</popupnotification>
--- a/browser/modules/ExtensionsUI.jsm
+++ b/browser/modules/ExtensionsUI.jsm
@@ -242,57 +242,54 @@ this.ExtensionsUI = {
let bundle = Services.strings.createBundle(BROWSER_PROPERTIES);
let strings = {};
strings.acceptText = bundle.GetStringFromName("webext.defaultSearchYes.label");
strings.acceptKey = bundle.GetStringFromName("webext.defaultSearchYes.accessKey");
strings.cancelText = bundle.GetStringFromName("webext.defaultSearchNo.label");
strings.cancelKey = bundle.GetStringFromName("webext.defaultSearchNo.accessKey");
- let addonName = `<span class="addon-webext-name">${this._sanitizeName(name)}</span>`;
+ strings.addonName = name;
strings.text = bundle.formatStringFromName("webext.defaultSearch.description",
- [addonName, currentEngine, newEngine], 3);
+ ["<>", currentEngine, newEngine], 3);
resolve(this.showDefaultSearchPrompt(browser, strings, icon));
}
},
- // 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, ">");
- },
-
// Create a set of formatted strings for a permission prompt
_buildStrings(info) {
let bundle = Services.strings.createBundle(BROWSER_PROPERTIES);
-
let brandBundle = Services.strings.createBundle(BRAND_PROPERTIES);
let appName = brandBundle.GetStringFromName("brandShortName");
- let addonName = `<span class="addon-webext-name">${this._sanitizeName(info.addon.name)}</span>`;
+ let info2 = Object.assign({appName}, info);
- let info2 = Object.assign({appName, addonName}, info);
-
- return ExtensionData.formatPermissionStrings(info2, bundle);
+ let strings = ExtensionData.formatPermissionStrings(info2, bundle);
+ strings.addonName = info.addon.name;
+ return strings;
},
showPermissionsPrompt(browser, strings, icon, histkey) {
+ let message = {};
+ // Create the notification header element.
+ let header = strings.header;
+ header = header.split("<>");
+ message.start = header[0];
+ // Use the host element to display addon name in addon permission prompts.
+ message.host = strings.addonName;
+ message.end = header[1];
+
function eventCallback(topic) {
let doc = this.browser.ownerDocument;
if (topic == "showing") {
- // eslint-disable-next-line no-unsanitized/property
- doc.getElementById("addon-webext-perm-header").innerHTML = strings.header;
let textEl = doc.getElementById("addon-webext-perm-text");
- // eslint-disable-next-line no-unsanitized/property
- textEl.innerHTML = strings.text;
+ textEl.textContent = strings.text;
textEl.hidden = !strings.text;
let listIntroEl = doc.getElementById("addon-webext-perm-intro");
- listIntroEl.value = strings.listIntro;
+ listIntroEl.textContent = 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) {
@@ -333,86 +330,94 @@ this.ExtensionsUI = {
if (histkey) {
this.histogram.add(histkey + "Rejected");
}
resolve(false);
},
},
];
- win.PopupNotifications.show(browser, "addon-webext-permissions", "",
+ win.PopupNotifications.show(browser, "addon-webext-permissions", message,
"addons-notification-icon",
action, secondaryActions, popupOptions);
});
},
showDefaultSearchPrompt(browser, strings, icon) {
-// const kDefaultSearchHistKey = "defaultSearch";
+ let message = {};
+ // Create the notification header element.
+ let header = strings.text;
+ header = header.split("<>");
+ message.start = header[0];
+ // Use the host element to display addon name in addon notification prompts.
+ message.host = strings.addonName;
+ message.end = header[1];
+
return new Promise(resolve => {
let popupOptions = {
hideClose: true,
popupIconURL: icon || DEFAULT_EXTENSION_ICON,
persistent: false,
removeOnDismissal: true,
eventCallback(topic) {
- if (topic == "showing") {
- let doc = this.browser.ownerDocument;
- // eslint-disable-next-line no-unsanitized/property
- doc.getElementById("addon-webext-defaultsearch-text").innerHTML = strings.text;
- } else if (topic == "removed") {
+ if (topic == "removed") {
resolve(false);
}
}
};
let action = {
label: strings.acceptText,
accessKey: strings.acceptKey,
disableHighlight: true,
callback: () => {
-// this.histogram.add(kDefaultSearchHistKey + "Accepted");
resolve(true);
},
};
let secondaryActions = [
{
label: strings.cancelText,
accessKey: strings.cancelKey,
callback: () => {
-// this.histogram.add(kDefaultSearchHistKey + "Rejected");
resolve(false);
},
},
];
let win = browser.ownerGlobal;
- win.PopupNotifications.show(browser, "addon-webext-defaultsearch", "",
+ win.PopupNotifications.show(browser, "addon-webext-defaultsearch", message,
"addons-notification-icon",
action, secondaryActions, popupOptions);
});
},
showInstallNotification(target, addon) {
let win = target.ownerGlobal;
let popups = win.PopupNotifications;
- let name = this._sanitizeName(addon.name);
- let addonName = `<span class="addon-webext-name">${name}</span>`;
let addonIcon = '<image class="addon-addon-icon"/>';
let toolbarIcon = '<image class="addon-toolbar-icon"/>';
let brandBundle = win.document.getElementById("bundle_brand");
let appName = brandBundle.getString("brandShortName");
let bundle = win.gNavigatorBundle;
- let msg1 = bundle.getFormattedString("addonPostInstall.message1",
- [addonName, appName]);
let msg2 = bundle.getFormattedString("addonPostInstall.messageDetail",
[addonIcon, toolbarIcon]);
+ // Create the notification header element.
+ let message = {};
+ let header = bundle.getFormattedString("addonPostInstall.message1",
+ ["<>", appName]);
+ header = header.split("<>");
+ message.start = header[0];
+ // Use the host element to display addon name in addon permission prompts.
+ message.host = addon.name;
+ message.end = header[1];
+
return new Promise(resolve => {
let action = {
label: bundle.getString("addonPostInstall.okay.label"),
accessKey: bundle.getString("addonPostInstall.okay.key"),
callback: resolve,
};
let icon = addon.isWebExtension ?
@@ -420,27 +425,24 @@ this.ExtensionsUI = {
"chrome://browser/skin/addons/addon-install-installed.svg";
let options = {
hideClose: true,
timeout: Date.now() + 30000,
popupIconURL: icon,
eventCallback(topic) {
if (topic == "showing") {
let doc = this.browser.ownerDocument;
- // eslint-disable-next-line no-unsanitized/property
- doc.getElementById("addon-installed-notification-header")
- .unsafeSetInnerHTML(msg1);
// eslint-disable-next-line no-unsanitized/property
doc.getElementById("addon-installed-notification-message")
.unsafeSetInnerHTML(msg2);
} else if (topic == "dismissed") {
resolve();
}
}
};
- popups.show(target, "addon-installed", "", "addons-notification-icon",
+ popups.show(target, "addon-installed", message, "addons-notification-icon",
action, null, options);
});
},
};
EventEmitter.decorate(ExtensionsUI);
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -256,36 +256,25 @@ html|*.addon-webext-perm-list {
padding-inline-start: 10px;
}
.addon-webext-perm-text {
margin-inline-start: 0;
}
.popup-notification-description[popupid="addon-webext-permissions"],
-.popup-notification-description[popupid="addon-installed"] {
- display: none;
+.popup-notification-description[popupid="addon-webext-permissions-notification"] {
+ margin-inline-start: -1px;
}
.addon-webext-perm-notification-content,
.addon-installed-notification-content {
margin-top: 0;
}
-#addon-webext-perm-header {
- /* Align the text more closely with the icon by clearing some top line height. */
- margin-top: -1px;
- margin-inline-start: 0;
-}
-
-#addon-installed-notification-header {
- /* Align the text more closely with the icon by clearing some top line height. */
- margin-top: -1px;
-}
-
.addon-webext-name {
display: inline;
font-weight: bold;
margin: 0;
}
.addon-addon-icon,
.addon-toolbar-icon {
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -957,36 +957,25 @@ html|*.addon-webext-perm-list {
padding-inline-start: 10px;
}
.addon-webext-perm-text {
margin-inline-start: 0;
}
.popup-notification-description[popupid="addon-webext-permissions"],
-.popup-notification-description[popupid="addon-installed"] {
- display: none;
+.popup-notification-description[popupid="addon-webext-permissions-notification"] {
+ margin-inline-start: -1px;
}
.addon-webext-perm-notification-content,
.addon-installed-notification-content {
margin-top: 0;
}
-#addon-webext-perm-header {
- /* Align the text more closely with the icon by clearing some top line height. */
- margin-top: -1px;
- margin-inline-start: 0;
-}
-
-#addon-installed-notification-header {
- /* Align the text more closely with the icon by clearing some top line height. */
- margin-top: -1px;
-}
-
.addon-webext-name {
display: inline;
font-weight: bold;
margin: 0;
}
.addon-addon-icon,
.addon-toolbar-icon {
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -765,36 +765,25 @@ html|*.addon-webext-perm-list {
padding-inline-start: 10px;
}
.addon-webext-perm-text {
margin-inline-start: 0;
}
.popup-notification-description[popupid="addon-webext-permissions"],
-.popup-notification-description[popupid="addon-installed"] {
- display: none;
+.popup-notification-description[popupid="addon-webext-permissions-notification"] {
+ margin-inline-start: -1px;
}
.addon-webext-perm-notification-content,
.addon-installed-notification-content {
margin-top: 0;
}
-#addon-webext-perm-header {
- /* Align the text more closely with the icon by clearing some top line height. */
- margin-top: -1px;
- margin-inline-start: 0;
-}
-
-#addon-installed-notification-header {
- /* Align the text more closely with the icon by clearing some top line height. */
- margin-top: -1px;
-}
-
.addon-webext-name {
display: inline;
font-weight: bold;
margin: 0;
}
.addon-addon-icon,
.addon-toolbar-icon {
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -861,33 +861,33 @@ class ExtensionData {
* Formats all the strings for a permissions dialog/notification.
*
* @param {object} info Information about the permissions being requested.
*
* @param {array<string>} info.permissions.origins
* Origin permissions requested.
* @param {array<string>} 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.
+ * for various elements of a permission dialog. The "header"
+ * property on this object is the notification header text
+ * and it has the string "<>" as a placeholder for the
+ * addon name.
*/
static formatPermissionStrings(info, bundle) {
let result = {};
let perms = info.permissions || {origins: [], permissions: []};
// First classify our host permissions
let allUrls = false, wildcards = new Set(), sites = new Set();
@@ -966,48 +966,48 @@ class ExtensionData {
} catch (err) {
// We deliberately do not include all permissions in the prompt.
// So if we don't find one then just skip it.
}
}
const haveAccessKeys = (AppConstants.platform !== "android");
- result.header = bundle.formatStringFromName("webextPerms.header", [info.addonName], 1);
+ result.header = bundle.formatStringFromName("webextPerms.header", ["<>"], 1);
result.text = info.unsigned ?
bundle.GetStringFromName("webextPerms.unsignedWarning") : "";
result.listIntro = bundle.GetStringFromName("webextPerms.listIntro");
result.acceptText = bundle.GetStringFromName("webextPerms.add.label");
result.cancelText = bundle.GetStringFromName("webextPerms.cancel.label");
if (haveAccessKeys) {
result.acceptKey = bundle.GetStringFromName("webextPerms.add.accessKey");
result.cancelKey = bundle.GetStringFromName("webextPerms.cancel.accessKey");
}
if (info.type == "sideload") {
- result.header = bundle.formatStringFromName("webextPerms.sideloadHeader", [info.addonName], 1);
+ result.header = bundle.formatStringFromName("webextPerms.sideloadHeader", ["<>"], 1);
let key = result.msgs.length == 0 ?
"webextPerms.sideloadTextNoPerms" : "webextPerms.sideloadText2";
result.text = bundle.GetStringFromName(key);
result.acceptText = bundle.GetStringFromName("webextPerms.sideloadEnable.label");
result.cancelText = bundle.GetStringFromName("webextPerms.sideloadCancel.label");
if (haveAccessKeys) {
result.acceptKey = bundle.GetStringFromName("webextPerms.sideloadEnable.accessKey");
result.cancelKey = bundle.GetStringFromName("webextPerms.sideloadCancel.accessKey");
}
} else if (info.type == "update") {
- result.header = "";
- result.text = bundle.formatStringFromName("webextPerms.updateText", [info.addonName], 1);
+ result.header = bundle.formatStringFromName("webextPerms.updateText", ["<>"], 1);
+ result.text = "";
result.acceptText = bundle.GetStringFromName("webextPerms.updateAccept.label");
if (haveAccessKeys) {
result.acceptKey = bundle.GetStringFromName("webextPerms.updateAccept.accessKey");
}
} else if (info.type == "optional") {
- result.header = bundle.formatStringFromName("webextPerms.optionalPermsHeader", [info.addonName], 1);
+ result.header = bundle.formatStringFromName("webextPerms.optionalPermsHeader", ["<>"], 1);
result.text = "";
result.listIntro = bundle.GetStringFromName("webextPerms.optionalPermsListIntro");
result.acceptText = bundle.GetStringFromName("webextPerms.optionalPermsAllow.label");
result.cancelText = bundle.GetStringFromName("webextPerms.optionalPermsDeny.label");
if (haveAccessKeys) {
result.acceptKey = bundle.GetStringFromName("webextPerms.optionalPermsAllow.accessKey");
result.cancelKey = bundle.GetStringFromName("webextPerms.optionalPermsDeny.accessKey");
}
--- a/toolkit/modules/PopupNotifications.jsm
+++ b/toolkit/modules/PopupNotifications.jsm
@@ -772,25 +772,19 @@ PopupNotifications.prototype = {
popupnotification = doc.createElementNS(XUL_NS, "popupnotification");
// Create the notification description element.
// Adding an if condition to check if n.message(i.e. the notification-description-text) is a string or an object.
if (typeof n.message == "string") {
popupnotification.setAttribute("label", n.message);
} else {
- if (n.message.start) {
- popupnotification.setAttribute("label", n.message.start);
- }
- if (n.message.host) {
- popupnotification.setAttribute("hostname", n.message.host);
- }
- if (n.message.end) {
- popupnotification.setAttribute("endlabel", n.message.end);
- }
+ popupnotification.setAttribute("label", n.message.start || "");
+ popupnotification.setAttribute("hostname", n.message.host || "");
+ popupnotification.setAttribute("endlabel", n.message.end || "");
}
popupnotification.setAttribute("id", popupnotificationID);
popupnotification.setAttribute("popupid", n.id);
popupnotification.setAttribute("oncommand", "PopupNotifications._onCommand(event);");
if (Services.prefs.getBoolPref("privacy.permissionPrompts.showCloseButton")) {
popupnotification.setAttribute("closebuttoncommand", "PopupNotifications._onButtonEvent(event, 'secondarybuttoncommand');");
} else {