diff --git a/chrome/content/bindings/extensions.xml b/chrome/content/bindings/extensions.xml
--- a/chrome/content/bindings/extensions.xml
+++ b/chrome/content/bindings/extensions.xml
@@ -18,20 +18,21 @@
-
+
-
+
+
@@ -113,20 +114,20 @@
-
+
-
+
diff --git a/chrome/content/extensions.js b/chrome/content/extensions.js
--- a/chrome/content/extensions.js
+++ b/chrome/content/extensions.js
@@ -55,17 +55,17 @@ var ExtensionsView = {
_list: null,
_localItem: null,
_repoItem: null,
_msg: null,
_dloadmgr: null,
_restartCount: 0,
_observerIndex: -1,
- _isXPInstallEnabled: function isXPInstallEnabled() {
+ _isXPInstallEnabled: function ev__isXPInstallEnabled() {
let enabled = false;
let locked = false;
try {
enabled = this._pref.getBoolPref("xpinstall.enabled");
if (enabled)
return true;
locked = this._pref.prefIsLocked("xpinstall.enabled");
}
@@ -302,23 +302,25 @@ var ExtensionsView = {
let addon = items[i];
// Some information is not directly accessible from the extmgr
let isDisabled = this._getRDFProperty(addon.id, "isDisabled") == "true";
let appDisabled = this._getRDFProperty(addon.id, "appDisabled");
let desc = this._getRDFProperty(addon.id, "description");
let optionsURL = this._getRDFProperty(addon.id, "optionsURL");
let opType = this._getRDFProperty(addon.id, "opType");
+ let updateable = this._getRDFProperty(addon.id, "updateable");
let listitem = this._createItem(addon, "local");
listitem.setAttribute("isDisabled", isDisabled);
listitem.setAttribute("appDisabled", appDisabled);
listitem.setAttribute("description", desc);
listitem.setAttribute("optionsURL", optionsURL);
listitem.setAttribute("opType", opType);
+ listitem.setAttribute("updateable", updateable);
this._list.insertBefore(listitem, this._repoItem);
}
},
enable: function ev_enable(aItem) {
let id = this._getIDFromURI(aItem.id);
this._extmgr.enableItem(id);
@@ -505,16 +507,42 @@ var ExtensionsView = {
BrowserUI.newTab(uri);
BrowserUI.hidePanel();
}
},
resetSearch: function ev_resetSearch() {
document.getElementById("addons-search-text").value = "";
this.getAddonsFromRepo("");
+ },
+
+ updateAll: function ev_updateAll() {
+ if (!this._isXPInstallEnabled())
+ return;
+
+ // To support custom views we check the add-ons displayed in the list
+ let items = [];
+ let start = this._localItem.nextSibling;
+ let end = this._repoItem;
+
+ while (start != end) {
+ if (start.getAttribute("updateable") != "false")
+ items.push(this._extmgr.getItemForID(start.getAttribute("addonID")));
+ start = start.nextSibling;
+ }
+
+ if (items.length > 0) {
+ let listener = new UpdateCheckListener();
+ this._extmgr.update(items, items.length, Ci.nsIExtensionManager.UPDATE_CHECK_NEWVERSION, listener);
+ }
+
+ if (this._list.selectedItem)
+ this._list.selectedItem.focus();
+
+ this._pref.setBoolPref("extensions.update.notifyUser", false);
}
};
///////////////////////////////////////////////////////////////////////////////
// nsIAddonSearchResultsCallback for the recommended search
var RecommendedSearchResults = {
cache: null,
@@ -662,15 +690,94 @@ XPInstallDownloadManager.prototype = {
element.setAttribute("opType", "needs-install");
}
var progress = Math.round((aValue / aMaxValue) * 100);
element.setAttribute("progress", progress);
},
/////////////////////////////////////////////////////////////////////////////
// nsISupports
- QueryInterface: function (aIID) {
+ QueryInterface: function(aIID) {
if (!aIID.equals(Ci.nsIAddonInstallListener) &&
!aIID.equals(Ci.nsISupports))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
}
};
+
+///////////////////////////////////////////////////////////////////////////////
+// Add-on update listener. Starts a download for any add-on with a viable
+// update waiting
+function UpdateCheckListener() {
+}
+
+UpdateCheckListener.prototype = {
+ /////////////////////////////////////////////////////////////////////////////
+ // nsIAddonUpdateCheckListener
+ onUpdateStarted: function() {
+ },
+
+ onUpdateEnded: function() {
+ },
+
+ onAddonUpdateStarted: function(addon) {
+ if (!document)
+ return;
+
+ let strings = document.getElementById("bundle_browser");
+ let element = document.getElementById(PREFIX_ITEM_URI + addon.id);
+ element.setAttribute("loading", "true");
+ element.setAttribute("updateStatus", strings.getString("addonUpdate.checking"));
+ },
+
+ onAddonUpdateEnded: function(addon, status) {
+ if (!document)
+ return;
+
+ let strings = document.getElementById("bundle_browser");
+ let element = document.getElementById(PREFIX_ITEM_URI + addon.id);
+ element.removeAttribute("loading");
+
+ let updateable = false;
+ const nsIAUCL = Ci.nsIAddonUpdateCheckListener;
+ switch (status) {
+ case nsIAUCL.STATUS_UPDATE:
+ var statusMsg = strings.getFormattedString("addonUpdate.updated", [addon.version]);
+ updateable = true;
+ break;
+ case nsIAUCL.STATUS_VERSIONINFO:
+ statusMsg = strings.getString("addonUpdate.compatibility");
+ break;
+ case nsIAUCL.STATUS_FAILURE:
+ statusMsg = strings.getString("addonUpdate.error");
+ break;
+ case nsIAUCL.STATUS_DISABLED:
+ statusMsg = strings.getString("addonUpdate.disabled");
+ break;
+ case nsIAUCL.STATUS_APP_MANAGED:
+ case nsIAUCL.STATUS_NO_UPDATE:
+ statusMsg = strings.getString("addonUpdate.noupdate");
+ break;
+ case nsIAUCL.STATUS_NOT_MANAGED:
+ statusMsg = strings.getString("addonUpdate.notsupported");
+ break;
+ case nsIAUCL.STATUS_READ_ONLY:
+ statusMsg = strings.getString("addonUpdate.notsupported");
+ break;
+ default:
+ statusMsg = strings.getString("addonUpdate.noupdate");
+ }
+ element.setAttribute("updateStatus", statusMsg);
+
+ if (updateable) {
+ let item = ExtensionsView._extmgr.getItemForID(addon.id);
+ ExtensionsView._extmgr.addDownloads([item], 1, null);
+ }
+ },
+
+ QueryInterface: function(aIID) {
+ if (!aIID.equals(Ci.nsIAddonUpdateCheckListener) &&
+ !aIID.equals(Ci.nsISupports))
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ return this;
+ }
+};
+
diff --git a/locales/en-US/chrome/browser.dtd b/locales/en-US/chrome/browser.dtd
--- a/locales/en-US/chrome/browser.dtd
+++ b/locales/en-US/chrome/browser.dtd
@@ -38,16 +38,17 @@
+
diff --git a/locales/en-US/chrome/browser.properties b/locales/en-US/chrome/browser.properties
--- a/locales/en-US/chrome/browser.properties
+++ b/locales/en-US/chrome/browser.properties
@@ -14,16 +14,24 @@ addonsSearchSuccess.button=Clear search
addonsSearchSuccess.button=Clear search
addonsConfirmInstall.title=Installing Add-on
addonsConfirmInstall.install=Install
addonType.2=Extension
addonType.4=Theme
addonType.8=Locale
+
+addonUpdate.checking=Checking for updates…
+addonUpdate.updated=Updated to %S
+addonUpdate.compatibility=A compatibility update has been applied
+addonUpdate.noupdate=No updates were found
+addonUpdate.notsupported=Updates not supported
+addonUpdate.disabled=Updates are disabled
+addonUpdate.error=An error occurred
# Download Manager
# LOCALIZATION NOTE (Status): — is the "em dash" (long dash)
# #1 download size for FINISHED or download state; #2 host (e.g., eTLD + 1, IP)
downloadsStatus=#1 — #2
downloadsUnknownSize=Unknown size
# LOCALIZATION NOTE (KnownSize): #1 size number; #2 size unit
downloadsKnownSize=#1 #2
diff --git a/themes/hildon/platform.css b/themes/hildon/platform.css
--- a/themes/hildon/platform.css
+++ b/themes/hildon/platform.css
@@ -299,16 +299,23 @@ richlistitem description.title {
richlistitem label.normal,
richlistitem description.normal {
color: gray;
font-size: 60% !important;
white-space: pre-wrap;
}
+richlistitem label.normal-bold,
+richlistitem description.normal-bold {
+ font-weight: bold;
+ font-size: 60% !important;
+ white-space: pre-wrap;
+}
+
richlistitem[selected="true"] {
color: black;
background-color: white;
}
richlistitem.section-header,
richlistitem[selected="true"].section-header {
font-weight: bold;
diff --git a/themes/wince/platform.css b/themes/wince/platform.css
--- a/themes/wince/platform.css
+++ b/themes/wince/platform.css
@@ -447,16 +447,23 @@ richlistitem description.title {
richlistitem label.normal,
richlistitem description.normal {
color: gray;
font-size: 8pt !important;
white-space: pre-wrap;
}
+richlistitem label.normal-bold,
+richlistitem description.normal-bold {
+ font-weight: bold;
+ font-size: 60% !important;
+ white-space: pre-wrap;
+}
+
richlistitem[selected="true"] {
color: black;
background-color: white;
}
richlistitem.section-header,
richlistitem[selected="true"].section-header {
font-weight: bold;