Bug 1308296 Show post-install notification r=florian
MozReview-Commit-ID: KenyFW6MyDO
--- a/browser/base/content/popup-notifications.inc
+++ b/browser/base/content/popup-notifications.inc
@@ -75,8 +75,15 @@
<popupnotification id="addon-webext-permissions-notification" hidden="true">
<popupnotificationcontent 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-installed-notification" hidden="true">
+ <popupnotificationcontent orient="vertical">
+ <description id="addon-installed-notification-header"/>
+ <description id="addon-installed-notification-message"/>
+ </popupnotificationcontent>
+ </popupnotification>
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -114,16 +114,30 @@ webextPerms.hostDescription.oneSite=Acce
# 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 (addonPostInstall.message)
+# %1$S is replaced with the localized named of the extension that was
+# just installed.
+# %2$S is replaced with the localized name of the application.
+addonPostInstall.message1=%1$S has been added to %2$S.
+
+# LOCALIZATION NOTE (addonPostInstall.message2)
+# %1$S is replaced with the localized name of the extension.
+# %2$S is replaced with the icon for the add-ons menu.
+# %3$S is replaced with the icon for the toolbar menu.
+# Note, this string will be used as raw markup. Avoid characters like <, >, &
+addonPostInstall.message2=Manage %1$S by clicking %2$S in the %3$S menu.
+addonPostInstall.okay.label=OK
+addonPostInstall.okay.key=O
# 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
--- a/browser/modules/ExtensionsUI.jsm
+++ b/browser/modules/ExtensionsUI.jsm
@@ -17,27 +17,28 @@ XPCOMUtils.defineLazyModuleGetter(this,
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);
-const DEFAULT_EXENSION_ICON = "chrome://mozapps/skin/extensions/extensionGeneric.svg";
+const DEFAULT_EXTENSION_ICON = "chrome://mozapps/skin/extensions/extensionGeneric.svg";
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);
Services.obs.addObserver(this, "webextension-update-permissions", false);
+ Services.obs.addObserver(this, "webextension-install-notify", false);
this._checkForSideloaded();
},
_checkForSideloaded() {
AddonManager.getAllAddons(addons => {
// Check for any side-loaded addons that the user is allowed
// to enable.
@@ -136,16 +137,19 @@ this.ExtensionsUI = {
reply(true);
} else {
info.permissions = perms;
this.showPermissionsPrompt(target, info).then(reply);
}
} else if (topic == "webextension-update-permissions") {
this.updates.add(subject.wrappedJSObject);
this.emit("change");
+ } else if (topic == "webextension-install-notify") {
+ let {target, addon} = subject.wrappedJSObject;
+ this.showInstallNotification(target, addon);
}
},
showPermissionsPrompt(target, info) {
let perms = info.permissions;
if (!perms) {
return Promise.resolve();
}
@@ -306,11 +310,52 @@ this.ExtensionsUI = {
{
label: cancelText,
accessKey: cancelKey,
callback: () => resolve(false),
},
], popupOptions);
});
},
+
+ showInstallNotification(target, addon) {
+ let win = target.ownerGlobal;
+ let popups = win.PopupNotifications;
+
+ let addonLabel = `<label class="addon-webext-name">${addon.name}</label>`;
+ 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",
+ [addonLabel, appName]);
+ let msg2 = bundle.getFormattedString("addonPostInstall.message2",
+ [addonLabel, addonIcon, toolbarIcon]);
+
+ let action = {
+ label: bundle.getString("addonPostInstall.okay.label"),
+ accessKey: bundle.getString("addonPostInstall.okay.key"),
+ callback: () => {},
+ };
+
+ let options = {
+ hideClose: true,
+ popupIconURL: addon.iconURL || DEFAULT_EXTENSION_ICON,
+ eventCallback(topic) {
+ if (topic == "showing") {
+ let doc = this.browser.ownerDocument;
+ doc.getElementById("addon-installed-notification-header")
+ .innerHTML = msg1;
+ doc.getElementById("addon-installed-notification-message")
+ .innerHTML = msg2;
+ }
+ }
+ };
+
+ popups.show(target, "addon-installed", "", "addons-notification-icon",
+ action, null, options);
+ },
};
EventEmitter.decorate(ExtensionsUI);
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -837,16 +837,30 @@ menuitem.bookmark-item {
font-size: 1.3em;
}
.addon-webext-name {
font-weight: bold;
margin: 0;
}
+.addon-addon-icon {
+ width: 14px;
+ height: 14px;
+ list-style-image: url("chrome://browser/skin/menuPanel.svg");
+ -moz-image-region: rect(0px, 288px, 32px, 256px);
+}
+
+.addon-toolbar-icon {
+ width: 14px;
+ height: 14px;
+ list-style-image: url("chrome://browser/skin/Toolbar.png");
+ -moz-image-region: rect(0, 486px, 18px, 468px);
+}
+
/* Notification icon box */
.notification-anchor-icon:-moz-focusring {
outline: 1px dotted -moz-DialogText;
}
/* Translation infobar */
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -3095,16 +3095,30 @@ menulist.translate-infobar-element > .me
font-size: 1.3em;
}
.addon-webext-name {
font-weight: bold;
margin: 0;
}
+.addon-addon-icon {
+ width: 14px;
+ height: 14px;
+ list-style-image: url("chrome://browser/skin/menuPanel.svg");
+ -moz-image-region: rect(0px, 288px, 32px, 256px);
+}
+
+.addon-toolbar-icon {
+ width: 14px;
+ height: 14px;
+ list-style-image: url("chrome://browser/skin/Toolbar.png");
+ -moz-image-region: rect(0, 486px, 18px, 468px);
+}
+
/* Status panel */
.statuspanel-label {
margin: 0;
padding: 2px 4px;
background: linear-gradient(#fff, #ddd);
border: 1px none #ccc;
border-top-style: solid;
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2140,16 +2140,30 @@ toolbarbutton.bookmark-item[dragover="tr
font-size: 1.3em;
}
.addon-webext-name {
font-weight: bold;
margin: 0;
}
+.addon-addon-icon {
+ width: 14px;
+ height: 14px;
+ list-style-image: url("chrome://browser/skin/menuPanel.svg");
+ -moz-image-region: rect(0px, 288px, 32px, 256px);
+}
+
+.addon-toolbar-icon {
+ width: 14px;
+ height: 14px;
+ list-style-image: url("chrome://browser/skin/Toolbar.png");
+ -moz-image-region: rect(0, 486px, 18px, 468px);
+}
+
/* Notification icon box */
.notification-anchor-icon:-moz-focusring {
outline: 1px dotted -moz-DialogText;
}
/* Translation infobar */
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -2104,17 +2104,23 @@ var AddonManagerInternal = {
// If installing a theme that is disabled and can be enabled
// then enable it
if (install.addon.type == "theme" &&
install.addon.userDisabled == true &&
install.addon.appDisabled == false) {
install.addon.userDisabled = false;
}
- self.installNotifyObservers("addon-install-complete", browser, url, install);
+
+ if (WEBEXT_PERMISSION_PROMPTS) {
+ let subject = {wrappedJSObject: {target: browser, addon: install.addon}};
+ Services.obs.notifyObservers(subject, "webextension-install-notify", null);
+ } else {
+ self.installNotifyObservers("addon-install-complete", browser, url, install);
+ }
},
};
install.addListener(listener);
// Start downloading if it hasn't already begun
install.install();
},