Bug 605494 - UI for restartless addons [r=mfinkle]

This commit is contained in:
Wes Johnston 2011-01-04 17:20:30 -08:00
Родитель bbe35dc89a
Коммит f049ba389f
2 изменённых файлов: 141 добавлений и 78 удалений

Просмотреть файл

@ -690,7 +690,7 @@ var Browser = {
return null; return null;
}, },
addTab: function(aURI, aBringFront, aOwner, aParams) { addTab: function browser_addTab(aURI, aBringFront, aOwner, aParams) {
let params = aParams || {}; let params = aParams || {};
let newTab = new Tab(aURI, params); let newTab = new Tab(aURI, params);
newTab.owner = aOwner || null; newTab.owner = aOwner || null;
@ -1369,12 +1369,12 @@ nsBrowserAccess.prototype = {
return browser; return browser;
}, },
openURI: function(aURI, aOpener, aWhere, aContext) { openURI: function browser_openURI(aURI, aOpener, aWhere, aContext) {
let browser = this._getBrowser(aURI, aOpener, aWhere, aContext); let browser = this._getBrowser(aURI, aOpener, aWhere, aContext);
return browser ? browser.contentWindow : null; return browser ? browser.contentWindow : null;
}, },
openURIInFrame: function(aURI, aOpener, aWhere, aContext) { openURIInFrame: function browser_openURIInFrame(aURI, aOpener, aWhere, aContext) {
let browser = this._getBrowser(aURI, aOpener, aWhere, aContext); let browser = this._getBrowser(aURI, aOpener, aWhere, aContext);
return browser ? browser.QueryInterface(Ci.nsIFrameLoaderOwner) : null; return browser ? browser.QueryInterface(Ci.nsIFrameLoaderOwner) : null;
}, },

Просмотреть файл

@ -278,6 +278,42 @@ var ExtensionsView = {
this.hideOptions(); this.hideOptions();
}, },
_createLocalAddon: function ev__createLocalAddon(aAddon) {
let strings = Elements.browserBundle;
let appManaged = (aAddon.scope == AddonManager.SCOPE_APPLICATION);
let opType = this._getOpTypeForOperations(aAddon.pendingOperations);
let updateable = (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE) > 0;
let uninstallable = (aAddon.permissions & AddonManager.PERM_CAN_UNINSTALL) > 0;
let blocked = "";
switch(aAddon.blocklistState) {
case Ci.nsIBlocklistService.STATE_BLOCKED:
blocked = strings.getString("addonBlocked.blocked")
break;
case Ci.nsIBlocklistService.STATE_SOFTBLOCKED:
blocked = strings.getString("addonBlocked.softBlocked");
break;
case Ci.nsIBlocklistService.STATE_OUTDATED:
blocked = srings.getString("addonBlocked.outdated");
break;
}
let listitem = this._createItem(aAddon, "local");
listitem.setAttribute("isDisabled", !aAddon.isActive);
listitem.setAttribute("appDisabled", aAddon.appDisabled);
listitem.setAttribute("appManaged", appManaged);
listitem.setAttribute("description", aAddon.description);
listitem.setAttribute("optionsURL", aAddon.optionsURL);
listitem.setAttribute("opType", opType);
listitem.setAttribute("updateable", updateable);
listitem.setAttribute("isReadonly", !uninstallable);
if (blocked)
listitem.setAttribute("blockedStatus", blocked);
listitem.addon = aAddon;
return listitem;
},
getAddonsFromLocal: function ev_getAddonsFromLocal() { getAddonsFromLocal: function ev_getAddonsFromLocal() {
this.clearSection("local"); this.clearSection("local");
@ -286,41 +322,11 @@ var ExtensionsView = {
let strings = Strings.browser; let strings = Strings.browser;
let anyUpdateable = false; let anyUpdateable = false;
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
let addon = items[i]; let listitem = self._createLocalAddon(items[i]);
let appManaged = (addon.scope == AddonManager.SCOPE_APPLICATION); if ((items[i].permissions & AddonManager.PERM_CAN_UPGRADE) > 0)
let opType = self._getOpTypeForOperations(addon.pendingOperations);
let updateable = (addon.permissions & AddonManager.PERM_CAN_UPGRADE) > 0;
let uninstallable = (addon.permissions & AddonManager.PERM_CAN_UNINSTALL) > 0;
let blocked = "";
switch(addon.blocklistState) {
case Ci.nsIBlocklistService.STATE_BLOCKED:
blocked = strings.GetStringFromName("addonBlocked.blocked")
break;
case Ci.nsIBlocklistService.STATE_SOFTBLOCKED:
blocked = strings.GetStringFromName("addonBlocked.softBlocked");
break;
case Ci.nsIBlocklistService.STATE_OUTDATED:
blocked = srings.GetStringFromName("addonBlocked.outdated");
break;
}
if (updateable)
anyUpdateable = true; anyUpdateable = true;
let listitem = self._createItem(addon, "local"); self.addItem(listitem);
listitem.setAttribute("isDisabled", !addon.isActive);
listitem.setAttribute("appDisabled", addon.appDisabled);
listitem.setAttribute("appManaged", appManaged);
listitem.setAttribute("description", addon.description);
listitem.setAttribute("optionsURL", addon.optionsURL ? addon.optionsURL : "");
listitem.setAttribute("opType", opType);
listitem.setAttribute("updateable", updateable);
listitem.setAttribute("isReadonly", !uninstallable);
if (blocked)
listitem.setAttribute("blockedStatus", blocked);
listitem.addon = addon;
self._list.insertBefore(listitem, self._repoItem);
} }
// Load the search engines // Load the search engines
@ -349,7 +355,7 @@ var ExtensionsView = {
listitem.setAttribute("optionsURL", ""); listitem.setAttribute("optionsURL", "");
listitem.setAttribute("opType", engine.hidden ? "needs-disable" : ""); listitem.setAttribute("opType", engine.hidden ? "needs-disable" : "");
listitem.setAttribute("updateable", "false"); listitem.setAttribute("updateable", "false");
self._list.insertBefore(listitem, self._repoItem); self.addItem(listitem);
} }
if (engines.length + items.length == 0) if (engines.length + items.length == 0)
@ -360,6 +366,19 @@ var ExtensionsView = {
}); });
}, },
addItem : function ev_addItem(aItem, aPosition) {
if (aPosition == "repo")
return this._list.appendChild(aItem);
else if (aPosition == "local")
return this._list.insertBefore(aItem, this._localItem.nextSibling);
else
return this._list.insertBefore(aItem, this._repoItem);
},
removeItem : function ev_moveItem(aItem) {
this._list.removeChild(aItem);
},
enable: function ev_enable(aItem) { enable: function ev_enable(aItem) {
let opType; let opType;
if (aItem.getAttribute("type") == "search") { if (aItem.getAttribute("type") == "search") {
@ -386,10 +405,13 @@ var ExtensionsView = {
aItem.addon.userDisabled = false; aItem.addon.userDisabled = false;
opType = this._getOpTypeForOperations(aItem.addon.pendingOperations); opType = this._getOpTypeForOperations(aItem.addon.pendingOperations);
if (opType == "needs-enable") if (aItem.addon.pendingOperations & AddonManager.PENDING_ENABLE) {
this.showRestart(); this.showRestart();
else } else {
this.hideRestart(); aItem.removeAttribute("isDisabled");
if (aItem.getAttribute("opType") == "needs-disable")
this.hideRestart();
};
} }
aItem.setAttribute("opType", opType); aItem.setAttribute("opType", opType);
@ -408,10 +430,13 @@ var ExtensionsView = {
aItem.addon.userDisabled = true; aItem.addon.userDisabled = true;
opType = this._getOpTypeForOperations(aItem.addon.pendingOperations); opType = this._getOpTypeForOperations(aItem.addon.pendingOperations);
if (opType == "needs-disable") if (aItem.addon.pendingOperations & AddonManager.PENDING_DISABLE) {
this.showRestart(); this.showRestart();
else } else {
this.hideRestart(); aItem.setAttribute("isDisabled", !aItem.addon.isActive);
if (aItem.getAttribute("opType") == "needs-enable")
this.hideRestart();
}
} }
aItem.setAttribute("opType", opType); aItem.setAttribute("opType", opType);
@ -427,18 +452,26 @@ var ExtensionsView = {
// the search-engine-modified observer in browser.js will take care of // the search-engine-modified observer in browser.js will take care of
// updating the list // updating the list
} else { } else {
if (!aItem.addon) {
this._list.removeChild(aItem);
return;
}
aItem.addon.uninstall(); aItem.addon.uninstall();
opType = this._getOpTypeForOperations(aItem.addon.pendingOperations); opType = this._getOpTypeForOperations(aItem.addon.pendingOperations);
if (opType == "needs-uninstall") if (aItem.addon.pendingOperations & AddonManager.PENDING_UNINSTALL) {
this.showRestart(); this.showRestart();
// A disabled addon doesn't need a restart so it has no pending ops and // A disabled addon doesn't need a restart so it has no pending ops and
// can't be cancelled // can't be cancelled
if (!aItem.addon.isActive && opType == "") if (!aItem.addon.isActive && opType == "")
opType = "needs-uninstall"; opType = "needs-uninstall";
aItem.setAttribute("opType", opType); aItem.setAttribute("opType", opType);
} else {
this._list.removeChild(aItem);
}
} }
}, },
@ -482,10 +515,7 @@ var ExtensionsView = {
item.setAttribute("hidebutton", "true"); item.setAttribute("hidebutton", "true");
item.setAttribute("hidethrobber", aHideThrobber); item.setAttribute("hidethrobber", aHideThrobber);
if (aSection == "repo") this.addItem(item, aSection);
this._list.appendChild(item);
else
this._list.insertBefore(item, this._repoItem);
return item; return item;
}, },
@ -544,7 +574,7 @@ var ExtensionsView = {
if (aShowRating) if (aShowRating)
listitem.setAttribute("rating", addon.averageRating); listitem.setAttribute("rating", addon.averageRating);
let item = this._list.appendChild(listitem); let item = this.addItem(listitem, "repo");
// Hide any overflow add-ons. The user can see them later by pressing the // Hide any overflow add-ons. The user can see them later by pressing the
// "See More" button // "See More" button
@ -594,7 +624,7 @@ var ExtensionsView = {
whatare.setAttribute("button", strings.GetStringFromName("addonsWhatAre.button")); whatare.setAttribute("button", strings.GetStringFromName("addonsWhatAre.button"));
whatare.setAttribute("onbuttoncommand", "BrowserUI.newTab('" + browseURL + "');"); whatare.setAttribute("onbuttoncommand", "BrowserUI.newTab('" + browseURL + "');");
this._list.appendChild(whatare); this.addItem(whatare, "repo");
if (aRecommendedAddons.length == 0 && aBrowseAddons.length == 0) { if (aRecommendedAddons.length == 0 && aBrowseAddons.length == 0) {
let msg = strings.GetStringFromName("addonsSearchNone.recommended"); let msg = strings.GetStringFromName("addonsSearchNone.recommended");
@ -631,7 +661,7 @@ var ExtensionsView = {
showmore.setAttribute("hidepage", totalAddons > kAddonPageSize ? "false" : "true"); showmore.setAttribute("hidepage", totalAddons > kAddonPageSize ? "false" : "true");
showmore.setAttribute("sitelabel", strings.GetStringFromName("addonsBrowseAll.browseSite")); showmore.setAttribute("sitelabel", strings.GetStringFromName("addonsBrowseAll.browseSite"));
showmore.setAttribute("onsitecommand", "ExtensionsView.showMoreResults('" + browseURL + "');"); showmore.setAttribute("onsitecommand", "ExtensionsView.showMoreResults('" + browseURL + "');");
this._list.appendChild(showmore); this.addItem(showmore, "repo");
let evt = document.createEvent("Events"); let evt = document.createEvent("Events");
evt.initEvent("ViewChanged", true, false); evt.initEvent("ViewChanged", true, false);
@ -674,7 +704,7 @@ var ExtensionsView = {
url = url.replace(/%TERMS%/g, encodeURIComponent(this.searchBox.value)); url = url.replace(/%TERMS%/g, encodeURIComponent(this.searchBox.value));
url = formatter.formatURL(url); url = formatter.formatURL(url);
showmore.setAttribute("onsitecommand", "ExtensionsView.showMoreResults('" + url + "');"); showmore.setAttribute("onsitecommand", "ExtensionsView.showMoreResults('" + url + "');");
this._list.appendChild(showmore); this.addItem(showmore, "repo");
} }
this.displaySectionMessage("repo", null, strings.GetStringFromName("addonsSearchSuccess2.button"), true); this.displaySectionMessage("repo", null, strings.GetStringFromName("addonsSearchSuccess2.button"), true);
@ -854,24 +884,53 @@ function AddonInstallListener() {
AddonInstallListener.prototype = { AddonInstallListener.prototype = {
onInstallEnded: function(aInstall, aAddon) { onInstallEnded: function(aInstall, aAddon) {
if (aInstall.existingAddon && (aInstall.existingAddon.pendingOperations & AddonManager.PENDING_UPGRADE)) let needsRestart = false;
ExtensionsView.showRestart("update"); let mode = "";
else if (aAddon.pendingOperations & AddonManager.PENDING_INSTALL) if (aInstall.existingAddon && (aInstall.existingAddon.pendingOperations & AddonManager.PENDING_UPGRADE)) {
ExtensionsView.showRestart("normal"); needsRestart = true;
mode = "update";
} else if (aAddon.pendingOperations & AddonManager.PENDING_INSTALL) {
needsRestart = true;
mode = "normal";
}
// if we already have a mode, then we need to show a restart notification
// otherwise, we are likely a bootstrapped addon
if (needsRestart)
ExtensionsView.showRestart(mode);
this._showInstallCompleteAlert(true, needsRestart);
// only do this if the view has already been inited
if (!ExtensionsView._list)
return;
let element = ExtensionsView.getElementForAddon(aAddon.id); let element = ExtensionsView.getElementForAddon(aAddon.id);
if (element) { if (!element) {
element = ExtensionsView._createLocalAddon(aAddon);
ExtensionsView.addItem(element, "local");
}
if (needsRestart) {
element.setAttribute("opType", "needs-restart"); element.setAttribute("opType", "needs-restart");
element.setAttribute("status", "success"); } else {
if (element.getAttribute("typeName") == "search") {
// If we are updating an add-on, change the status if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE)
if (element.hasAttribute("updating")) { document.getElementById("addons-update-all").disabled = false;
let strings = Strings.browser;
element.setAttribute("updateStatus", strings.formatStringFromName("addonUpdate.updated", [aAddon.version], 1)); ExtensionsView.removeItem(element);
element.removeAttribute("updating"); element = ExtensionsView._createLocalAddon(aAddon);
ExtensionsView.addItem(element, "local");
} }
} }
this._showInstallCompleteAlert(true);
element.setAttribute("status", "success");
// If we are updating an add-on, change the status
if (element.hasAttribute("updating")) {
let strings = Elements.browserBundle;
element.setAttribute("updateStatus", strings.getFormattedString("addonUpdate.updated", [aAddon.version]));
element.removeAttribute("updating");
}
}, },
onInstallFailed: function(aInstall, aError) { onInstallFailed: function(aInstall, aError) {
@ -930,7 +989,7 @@ AddonInstallListener.prototype = {
this.onInstallFailed(aInstall, aError); this.onInstallFailed(aInstall, aError);
}, },
onDownloadCancelled: function(aInstall, aAddon) { onDownloadCancelled: function(aInstall) {
let strings = Strings.browser; let strings = Strings.browser;
let brandBundle = Strings.brand; let brandBundle = Strings.brand;
let brandShortName = brandBundle.GetStringFromName("brandShortName"); let brandShortName = brandBundle.GetStringFromName("brandShortName");
@ -941,9 +1000,9 @@ AddonInstallListener.prototype = {
let error = (host || aInstall.error == 0) ? "addonError" : "addonLocalError"; let error = (host || aInstall.error == 0) ? "addonError" : "addonLocalError";
if (aInstall.error != 0) if (aInstall.error != 0)
error += aInstall.error; error += aInstall.error;
else if (aInstall.addon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED) else if (aInstall.addon && aInstall.addon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED)
error += "Blocklisted"; error += "Blocklisted";
else if (!aInstall.addon.isCompatible || !aInstall.addon.isPlatformCompatible) else if (aInstall.addon && (!aInstall.addon.isCompatible || !aInstall.addon.isPlatformCompatible))
error += "Incompatible"; error += "Incompatible";
else { else {
ExtensionsView.hideAlerts(); ExtensionsView.hideAlerts();
@ -960,10 +1019,14 @@ AddonInstallListener.prototype = {
ExtensionsView.showAlert(messageString); ExtensionsView.showAlert(messageString);
}, },
_showInstallCompleteAlert: function xpidm_showAlert(aSucceeded) { _showInstallCompleteAlert: function xpidm_showAlert(aSucceeded, aNeedsRestart) {
let strings = Strings.browser; let strings = Strings.browser;
let msg = aSucceeded ? strings.GetStringFromName("alertAddonsInstalled") : let stringName = "alertAddonsFail";
strings.GetStringFromName("alertAddonsFail"); if (aSucceeded) {
ExtensionsView.showAlert(msg); stringName = "alertAddonsInstalled";
if (!aNeedsRestart)
stringName += "NoRestart";
}
ExtensionsView.showAlert(strings.GetStringFromName(stringName));
}, },
}; };