Bug 408115: Add post-restart notification of new add-on installs. r=gavin.sharp, r=robstrong, a=beltzner

This commit is contained in:
2008-03-07 16:16:38 -08:00
parent f8c51aeb99
commit aa5b533705
7 changed files with 139 additions and 11 deletions

View File

@@ -45,6 +45,8 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/distribution.js");
const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
// Factory object
const BrowserGlueServiceFactory = {
_instance: null,
@@ -89,6 +91,9 @@ BrowserGlue.prototype = {
case "final-ui-startup":
this._onProfileStartup();
break;
case "sessionstore-windows-restored":
this._onBrowserStartup();
break;
case "browser:purge-session-history":
// reset the console service's error buffer
const cs = Cc["@mozilla.org/consoleservice;1"].
@@ -122,6 +127,7 @@ BrowserGlue.prototype = {
osvr.addObserver(this, "xpcom-shutdown", false);
osvr.addObserver(this, "prefservice:after-app-defaults", false);
osvr.addObserver(this, "final-ui-startup", false);
osvr.addObserver(this, "sessionstore-windows-restored", false);
osvr.addObserver(this, "browser:purge-session-history", false);
osvr.addObserver(this, "quit-application-requested", false);
osvr.addObserver(this, "quit-application-granted", false);
@@ -138,6 +144,7 @@ BrowserGlue.prototype = {
osvr.removeObserver(this, "xpcom-shutdown");
osvr.removeObserver(this, "prefservice:after-app-defaults");
osvr.removeObserver(this, "final-ui-startup");
osvr.removeObserver(this, "sessionstore-windows-restored");
osvr.removeObserver(this, "browser:purge-session-history");
osvr.removeObserver(this, "quit-application-requested");
osvr.removeObserver(this, "quit-application-granted");
@@ -202,6 +209,32 @@ BrowserGlue.prototype = {
this.Sanitizer.onShutdown();
},
// Browser startup complete. All initial windows have opened.
_onBrowserStartup: function()
{
var prefBranch = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
// If new add-ons were installed during startup open the add-ons manager.
if (prefBranch.prefHasUserValue(PREF_EM_NEW_ADDONS_LIST)) {
var args = Cc["@mozilla.org/supports-array;1"].
createInstance(Ci.nsISupportsArray);
var str = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
str.data = "";
args.AppendElement(str);
var str = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
str.data = prefBranch.getCharPref(PREF_EM_NEW_ADDONS_LIST);
args.AppendElement(str);
const EMURL = "chrome://mozapps/content/extensions/extensions.xul";
const EMFEATURES = "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable";
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
ww.openWindow(null, EMURL, "_blank", EMFEATURES, args);
prefBranch.clearUserPref(PREF_EM_NEW_ADDONS_LIST);
}
},
_onQuitRequest: function(aCancelQuit, aQuitType)
{
// If user has already dismissed quit request, then do nothing

View File

@@ -1,3 +1,7 @@
# LOCALIZATION NOTE: Semi-colon list of plural forms.
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
addonsPlural=add-on;add-ons
aboutWindowTitle=About %S
aboutWindowCloseButton=Close
aboutWindowVersionString=version %S
@@ -94,7 +98,7 @@ updateAvailableMsg=Version %S is available.
xpinstallDisabledMsgLocked=Software installation has been disabled by your system administrator.
xpinstallDisabledMsg=Software installation is currently disabled. Click Enable and try again.
newAddonsInstalledMsg=%S new add-ons have been installed.
newAddonsNotificationMsg=%S new %S installed.
safeModeMsg=All add-ons have been disabled by safe mode.
disabledCompatMsg=Add-on compatibility checking is disabled. You may have incompatible add-ons.
disabledUpdateSecurityMsg=Add-on update security checking is disabled. You may be compromised by updates.

View File

@@ -74,6 +74,7 @@ var gRetrievedResults = false;
var gRecommendedAddons = null;
var gRDF = null;
var gPendingInstalls = {};
var gNewAddons = [];
const PREF_EM_CHECK_COMPATIBILITY = "extensions.checkCompatibility";
const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity";
@@ -106,6 +107,7 @@ const OP_NEEDS_UNINSTALL = "needs-uninstall";
const OP_NEEDS_ENABLE = "needs-enable";
const OP_NEEDS_DISABLE = "needs-disable";
Components.utils.import("resource://gre/modules/PluralForm.jsm");
Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
///////////////////////////////////////////////////////////////////////////////
@@ -483,15 +485,8 @@ function showView(aView) {
else
document.getElementById("continueDialogButton").removeAttribute("default");
if (isThemes) {
if (gPref.getBoolPref(PREF_EXTENSIONS_DSS_SWITCHPENDING)) {
var item = getItemForInternalName(gCurrentTheme);
if (item)
setRestartMessage(item);
}
if (isThemes)
onAddonSelect();
}
updateGlobalCommands();
}
@@ -1097,6 +1092,8 @@ function Startup()
null, null, true, null);
}
gExtensionsView.builder.addListener(TemplateBuilderListener);
if ("arguments" in window) {
try {
var params = window.arguments[0].QueryInterface(Components.interfaces.nsIDialogParamBlock);
@@ -1119,6 +1116,36 @@ function Startup()
null, null, true, null);
document.title = getExtensionString("newUpdateWindowTitle", [getBrandShortName()]);
}
else if (window.arguments.length == 2) {
gNewAddons = window.arguments[1].split(",");
var addonsTerm = PluralForm.get(gNewAddons.length, getExtensionString("addonsPlural"));
showMessage("chrome://mozapps/skin/extensions/question.png",
getExtensionString("newAddonsNotificationMsg", [gNewAddons.length, addonsTerm]),
null, null, true, null);
var extensionCount = 0;
var themeCount = 0;
var localeCount = 0;
for (var i = 0; i < gNewAddons.length; i++) {
var item = gExtensionManager.getItemForID(gNewAddons[i]);
switch (item.type) {
case Ci.nsIUpdateItem.TYPE_EXTENSION:
extensionCount++;
break;
case Ci.nsIUpdateItem.TYPE_THEME:
themeCount++;
break;
case Ci.nsIUpdateItem.TYPE_LOCALE:
localeCount++;
break;
}
}
if (themeCount > extensionCount && themeCount > localeCount)
showView("themes");
else if (localeCount > extensionCount && localeCount > themeCount)
showView("locales");
else
showView("extensions");
}
else
showView(window.arguments[0]);
}
@@ -1141,6 +1168,8 @@ function Startup()
function Shutdown()
{
gExtensionsView.builder.removeListener(TemplateBuilderListener);
gPref.removeObserver(PREF_DSS_SKIN_TO_SELECT, gPrefObserver);
gPref.removeObserver(PREF_GENERAL_SKINS_SELECTEDSKIN, gPrefObserver);
if (gAddonRepository && gAddonRepository.isSearching)
@@ -1163,6 +1192,38 @@ function Shutdown()
window.removeEventListener("select", noUpdatesDismiss, true);
}
var TemplateBuilderListener = {
willRebuild: function(aBuilder) {
},
didRebuild: function(aBuilder) {
// Display has been rebuilt, update necessary attributes
if (gView == "extensions" || gView == "themes" || gView == "locales") {
for (var i = 0; i < gNewAddons.length; i++) {
var item = document.getElementById(PREFIX_ITEM_URI + gNewAddons[i]);
if (item)
item.setAttribute("newAddon", "true");
}
}
if (gView == "themes") {
if (gPref.getBoolPref(PREF_EXTENSIONS_DSS_SWITCHPENDING)) {
var item = getItemForInternalName(gCurrentTheme);
if (item)
setRestartMessage(item);
}
}
},
QueryInterface: function (aIID)
{
if (!aIID.equals(Components.interfaces.nsIXULBuilderListener) &&
!aIID.equals(Components.interfaces.nsISupports))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
}
};
///////////////////////////////////////////////////////////////////////////////
//
// XPInstall

View File

@@ -60,6 +60,7 @@ const PREF_EM_LAST_APP_VERSION = "extensions.lastAppVersion";
const PREF_EM_ENABLED_ITEMS = "extensions.enabledItems";
const PREF_UPDATE_COUNT = "extensions.update.count";
const PREF_UPDATE_DEFAULT_URL = "extensions.update.url";
const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
const PREF_EM_IGNOREMTIMECHANGES = "extensions.ignoreMTimeChanges";
const PREF_EM_DISABLEDOBSOLETE = "extensions.disabledObsolete";
const PREF_EM_EXTENSION_FORMAT = "extensions.%UUID%.";
@@ -173,6 +174,7 @@ var gLoggingEnabled = null;
var gCheckCompatibility = true;
var gCheckUpdateSecurity = true;
var gLocale = "en-US";
var gFirstRun = false;
/**
* Valid GUIDs fit this pattern.
@@ -1716,7 +1718,7 @@ Installer.prototype = {
// contents.rdf file at the location specified, malformed contents.rdf,
// etc. Set the pending op to be OP_NEEDS_UNINSTALL so that the
// extension is uninstalled properly during the subsequent uninstall
// pass in |ExtensionManager::_finalizeOperations|
// pass in |ExtensionManager::_finishOperations|
ERROR("upgradeThemeChrome: failed for theme " + this._id + " - why " +
"not convert to the new chrome.manifest format while you're at it? " +
"Failure exception: " + e);
@@ -1806,7 +1808,7 @@ Installer.prototype = {
// contents.rdf file at the location specified, malformed contents.rdf,
// etc. Set the pending op to be OP_NEEDS_UNINSTALL so that the
// extension is uninstalled properly during the subsequent uninstall
// pass in |ExtensionManager::_finalizeOperations|
// pass in |ExtensionManager::_finishOperations|
ERROR("upgradeExtensionChrome: failed for extension " + this._id + " - why " +
"not convert to the new chrome.manifest format while you're at it? " +
"Failure exception: " + e);
@@ -2281,6 +2283,7 @@ var StartupCache = {
// There is no change manifest for some reason, either we're in an initial
// state or something went wrong with one of the other files and the
// change manifest was removed. Return an empty dataset and rebuild.
gFirstRun = true;
return;
}
var fis = Cc["@mozilla.org/network/file-input-stream;1"].
@@ -3365,6 +3368,11 @@ ExtensionManager.prototype = {
var updatedTargetAppInfos = [];
var needsRestart = false;
var upgrades = [];
var newAddons = [];
var addons = getPref("getCharPref", PREF_EM_NEW_ADDONS_LIST, "");
if (addons != "")
newAddons = addons.split(",");
do {
// Enable and disable during startup so items that are changed in the
// ui can be reset to a no-op.
@@ -3402,6 +3410,7 @@ ExtensionManager.prototype = {
if (newTargetAppInfo)
updatedTargetAppInfos.push(newTargetAppInfo);
this._finalizeUpgrade(id, newLocation);
upgrades.push(id);
}
PendingOperations.clearItems(OP_NEEDS_UPGRADE);
@@ -3415,6 +3424,8 @@ ExtensionManager.prototype = {
if (newTargetAppInfo)
updatedTargetAppInfos.push(newTargetAppInfo);
this._finalizeInstall(id, null);
if (upgrades.indexOf(id) < 0 && newAddons.indexOf(id) < 0)
newAddons.push(id);
}
PendingOperations.clearItems(OP_NEEDS_INSTALL);
@@ -3427,6 +3438,9 @@ ExtensionManager.prototype = {
this._finalizeUninstall(id);
this._checkForUncoveredItem(id);
needsRestart = true;
var pos = newAddons.indexOf(id);
if (pos >= 0)
newAddons.splice(pos, 1);
}
PendingOperations.clearItems(OP_NEEDS_UNINSTALL);
@@ -3479,6 +3493,10 @@ ExtensionManager.prototype = {
// not to do any extra startup checking next time round.
this._updateManifests(needsRestart);
// Remember the list of add-ons that were installed this time around
// unless this was a new profile.
if (!gFirstRun && newAddons.length > 0)
gPref.setCharPref(PREF_EM_NEW_ADDONS_LIST, newAddons.join(","));
}
catch (e) {
ERROR("ExtensionManager:_finishOperations - failure, catching exception - lineno: " +

View File

@@ -52,6 +52,10 @@ richlistitem[isDisabled="true"] {
color: GrayText;
}
richlistitem[newAddon="true"] {
background-color: InfoBackground;
}
richlistitem[selected="true"] {
background-color: -moz-cellhighlight;
color: -moz-cellhighlighttext;

View File

@@ -57,6 +57,10 @@ richlistitem[isDisabled="true"] {
color: GrayText;
}
richlistitem[newAddon="true"] {
background-color: #fdf2ab;
}
richlistitem[selected="true"] {
background-color: Highlight;
color: HighlightText;

View File

@@ -51,6 +51,10 @@ richlistitem[isDisabled="true"] {
color: GrayText;
}
richlistitem[newAddon="true"] {
background-color: InfoBackground;
}
richlistitem[selected="true"] {
background-color: -moz-cellhighlight;
color: -moz-cellhighlighttext;