diff --git a/mozilla/toolkit/mozapps/extensions/content/extensions.css b/mozilla/toolkit/mozapps/extensions/content/extensions.css
index 7f5c6008107..28b434dbb12 100644
--- a/mozilla/toolkit/mozapps/extensions/content/extensions.css
+++ b/mozilla/toolkit/mozapps/extensions/content/extensions.css
@@ -8,18 +8,22 @@ extension {
-moz-box-orient: vertical;
}
-extension[install-state="pending"] {
- -moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#extension-pending");
+extension[state="waiting"] {
+ -moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#extension-waiting");
}
-extension[install-state="downloading"] {
+extension[state="downloading"] {
-moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#extension-downloading");
}
-extension[install-state="installing"] {
+extension[state="installing"] {
-moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#extension-installing");
}
+extension[state="done"] {
+ -moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#extension-done");
+}
+
extension[toBeDisabled="true"] {
-moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#extension-tobedisabled");
}
@@ -36,10 +40,28 @@ extension[toBeUninstalled="true"] {
-moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#extension-tobeuninstalled");
}
+
+
extension[itemType="theme"] {
-moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#theme");
}
+extension[itemType="theme"][state="waiting"] {
+ -moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#theme-waiting");
+}
+
+extension[itemType="theme"][state="downloading"] {
+ -moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#theme-downloading");
+}
+
+extension[itemType="theme"][state="installing"] {
+ -moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#theme-installing");
+}
+
+extension[itemType="theme"][state="done"] {
+ -moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#theme-done");
+}
+
.themePreviewArea {
width: 0px;
}
diff --git a/mozilla/toolkit/mozapps/extensions/content/extensions.js b/mozilla/toolkit/mozapps/extensions/content/extensions.js
index af9b16067c1..2ba90db627c 100644
--- a/mozilla/toolkit/mozapps/extensions/content/extensions.js
+++ b/mozilla/toolkit/mozapps/extensions/content/extensions.js
@@ -5,12 +5,14 @@ const kObserverServiceProgID = "@mozilla.org/observer-service;1";
const nsIUpdateItem = Components.interfaces.nsIUpdateItem;
var gExtensionManager = null;
-var gDownloadListener = null;
var gExtensionssView = null;
var gWindowState = "";
var gURIPrefix = ""; // extension or theme prefix
var gDSRoot = ""; // extension or theme root
var gGetMoreURL = "";
+var gCurrentTheme = "";
+var gDownloadManager = null;
+var gObserverIndex = -1;
const PREF_APP_ID = "app.id";
const PREF_EXTENSIONS_GETMORETHEMESURL = "extensions.getMoreThemesURL";
@@ -63,7 +65,8 @@ function onExtensionSelect(aEvent)
// Startup, Shutdown
function Startup()
{
- gWindowState = window.arguments[0];
+ gWindowState = window.location.search.substr("?type=".length, window.location.search.length);
+
var isExtensions = gWindowState == "extensions";
gURIPrefix = isExtensions ? "urn:mozilla:extension:" : "urn:mozilla:theme:";
gDSRoot = isExtensions ? "urn:mozilla:extension:root" : "urn:mozilla:theme:root";
@@ -134,14 +137,225 @@ function Startup()
win.setAttribute("width", isExtensions ? 400 : 500);
win.setAttribute("height", isExtensions ? 300 : 380);
}
+
+ // Now look and see if we're being opened by XPInstall
+ var gDownloadManager = new XPInstallDownloadManager();
+ var os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Components.interfaces.nsIObserverService);
+ os.addObserver(gDownloadManager, "xpinstall-download-started", false);
+
+ gObserverIndex = gExtensionManager.addDownloadObserver(gDownloadManager);
+
+ if ("arguments" in window) {
+ try {
+ var params = window.arguments[0].QueryInterface(Components.interfaces.nsIDialogParamBlock);
+ gDownloadManager.addDownloads(params);
+ }
+ catch (e) { }
+ }
}
function Shutdown()
{
if (gWindowState != "extensions")
gExtensionsView.removeEventListener("richview-select", onThemeSelect, false);
+
+ gExtensionManager.removeDownloadObserverAt(gObserverIndex);
+
+ var os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Components.interfaces.nsIObserverService);
+ os.removeObserver(gObserver, "xpinstall-download-started");
}
+///////////////////////////////////////////////////////////////////////////////
+//
+// XPInstall
+//
+
+function getURLSpecFromFile(aFile)
+{
+ var ioServ = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService);
+ var fph = ioServ.getProtocolHandler("file").QueryInterface(Components.interfaces.nsIFileProtocolHandler);
+ return fph.getURLSpecFromFile(aFile);
+}
+
+function XPInstallDownloadManager()
+{
+ var extensionsStrings = document.getElementById("extensionsStrings");
+ this._statusFormatKBMB = extensionsStrings.getString("statusFormatKBMB");
+ this._statusFormatKBKB = extensionsStrings.getString("statusFormatKBKB");
+ this._statusFormatMBMB = extensionsStrings.getString("statusFormatMBMB");
+}
+
+XPInstallDownloadManager.prototype = {
+ _statusFormat : null,
+ _statusFormatKBMB : null,
+ _statusFormatKBKB : null,
+ _statusFormatMBMB : null,
+
+ observe: function (aSubject, aTopic, aData)
+ {
+ if (aTopic == "xpinstall-download-started") {
+ var params = aSubject.QueryInterface(Components.interfaces.nsISupportsArray);
+ var paramBlock = params.GetElementAt(0).QueryInterface(Components.interfaces.nsISupportsInterfacePointer);
+ paramBlock = paramBlock.data.QueryInterface(Components.interfaces.nsIDialogParamBlock);
+ this.addDownloads(paramBlock);
+ }
+ },
+
+ addDownloads: function (aParams)
+ {
+ var numXPInstallItems = aParams.GetInt(1);
+ var isExtensions = gWindowState == "extensions";
+
+ var items = [];
+ for (var i = 0; i < numXPInstallItems;) {
+ var displayName = aParams.GetString(i++);
+ var url = aParams.GetString(i++);
+ var iconURL = aParams.GetString(i++);
+ if (!iconURL) {
+ iconURL = isExtensions ? "chrome://mozapps/skin/xpinstall/xpinstallItemGeneric.png" :
+ "chrome://mozapps/skin/extensions/themeGeneric.png";
+ }
+
+ var type = isExtensions ? nsIUpdateItem.TYPE_EXTENSION : nsIUpdateItem.TYPE_THEME;
+ // gExtensionManager.addDownload(displayName, url, iconURL, type);
+ var item = Components.classes["@mozilla.org/updates/item;1"]
+ .createInstance(Components.interfaces.nsIUpdateItem);
+ item.init(url, " ", displayName, -1, url, iconURL, "", type);
+ items.push(item);
+
+ // Advance the enumerator
+ var certName = aParams.GetString(i++);
+ }
+
+ gExtensionManager.addDownloads(items, items.length);
+ },
+
+ removeDownload: function (aEvent)
+ {
+
+ },
+
+ /////////////////////////////////////////////////////////////////////////////
+ // nsIExtensionDownloadProgressListener
+ onStateChange: function (aURL, aState, aValue)
+ {
+ const nsIXPIProgressDialog = Components.interfaces.nsIXPIProgressDialog;
+ var element = document.getElementById(aURL);
+ switch (aState) {
+ case nsIXPIProgressDialog.DOWNLOAD_START:
+ dump("*** download start\n");
+ element.setAttribute("state", "waiting");
+ element.setAttribute("progress", "0");
+ break;
+ case nsIXPIProgressDialog.DOWNLOAD_DONE:
+ dump("*** download done\n");
+ element.setAttribute("progress", "100");
+ break;
+ case nsIXPIProgressDialog.INSTALL_START:
+ dump("*** install start\n");
+ element.setAttribute("state", "installing");
+ break;
+ case nsIXPIProgressDialog.INSTALL_DONE:
+ dump("*** install done\n");
+ element.setAttribute("state", "done");
+ var msg;
+ if (aValue != 0) {
+ var xpinstallStrings = document.getElementById("xpinstallStrings");
+ try {
+ msg = xpinstallStrings.getString("error" + aValue);
+ }
+ catch (e) {
+ msg = xpinstallStrings.getFormattedString("unknown.error", [aValue]);
+ }
+ element.setAttribute("error", msg);
+ }
+ else {
+ // Remove the dummy, since we installed successfully
+ var type = gWindowState == "extensions" ? nsIUpdateItem.TYPE_EXTENSION
+ : nsIUpdateItem.TYPE_THEME;
+ gExtensionManager.removeDownload(aURL, type);
+ }
+ break;
+ case nsIXPIProgressDialog.DIALOG_CLOSE:
+ break;
+ }
+ },
+
+ _urls: { },
+ onProgress: function (aURL, aValue, aMaxValue)
+ {
+ var element = document.getElementById(aURL);
+ var percent = Math.round((aValue / aMaxValue) * 100);
+ if (percent > 1 && !(aURL in this._urls)) {
+ this._urls[aURL] = true;
+ element.setAttribute("state", "downloading");
+ }
+ element.setAttribute("progress", percent);
+
+ var KBProgress = parseInt(aValue/1024 + .5);
+ var KBTotal = parseInt(aMaxValue/1024 + .5);
+ element.setAttribute("status", this._formatKBytes(KBProgress, KBTotal));
+ },
+
+ _replaceInsert: function ( text, index, value )
+ {
+ var result = text;
+ var regExp = new RegExp( "#"+index );
+ result = result.replace( regExp, value );
+ return result;
+ },
+
+ // aBytes aTotalKBytes returns:
+ // x, < 1MB y < 1MB x of y KB
+ // x, < 1MB y >= 1MB x KB of y MB
+ // x, >= 1MB y >= 1MB x of y MB
+ _formatKBytes: function (aKBytes, aTotalKBytes)
+ {
+ var progressHasMB = parseInt(aKBytes/1000) > 0;
+ var totalHasMB = parseInt(aTotalKBytes/1000) > 0;
+
+ var format = "";
+ if (!progressHasMB && !totalHasMB) {
+ format = this._statusFormatKBKB;
+ format = this._replaceInsert(format, 1, aKBytes);
+ format = this._replaceInsert(format, 2, aTotalKBytes);
+ }
+ else if (progressHasMB && totalHasMB) {
+ format = this._statusFormatMBMB;
+ format = this._replaceInsert(format, 1, (aKBytes / 1000).toFixed(1));
+ format = this._replaceInsert(format, 2, (aTotalKBytes / 1000).toFixed(1));
+ }
+ else if (totalHasMB && !progressHasMB) {
+ format = this._statusFormatKBMB;
+ format = this._replaceInsert(format, 1, aKBytes);
+ format = this._replaceInsert(format, 2, (aTotalKBytes / 1000).toFixed(1));
+ }
+ else {
+ // This is an undefined state!
+ dump("*** huh?!\n");
+ }
+
+ return format;
+ },
+
+ /////////////////////////////////////////////////////////////////////////////
+ // nsISupports
+ QueryInterface: function (aIID)
+ {
+ if (!aIID.equals(Components.interfaces.nsIExtensionDownloadProgressListener) &&
+ !aIID.equals(Components.interfaces.nsISupports))
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ return this;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// View Event Handlers
+//
function onViewDoubleClick()
{
switch (gWindowState) {
diff --git a/mozilla/toolkit/mozapps/extensions/content/extensions.xml b/mozilla/toolkit/mozapps/extensions/content/extensions.xml
index b6df8861698..def533d6399 100644
--- a/mozilla/toolkit/mozapps/extensions/content/extensions.xml
+++ b/mozilla/toolkit/mozapps/extensions/content/extensions.xml
@@ -189,6 +189,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &extensionItem.waiting.label;
+
+
+
+
+
+
+ "extension-"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "extension-"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &extensionItem.installing.label;
+
+
+
+
+
+
+ "extension-"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "extension-"
+
+
+
@@ -213,5 +318,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &extensionItem.waiting.label;
+
+
+
+
+ "extension-"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "extension-"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &extensionItem.installing.label;
+
+
+
+
+ "extension-"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &extensionItem.done.label;
+
+
+
+
+ "extension-"
+
+
+
diff --git a/mozilla/toolkit/mozapps/extensions/content/extensions.xul b/mozilla/toolkit/mozapps/extensions/content/extensions.xul
index 06cc72b06c4..1230381ecdc 100644
--- a/mozilla/toolkit/mozapps/extensions/content/extensions.xul
+++ b/mozilla/toolkit/mozapps/extensions/content/extensions.xul
@@ -64,6 +64,7 @@
+
@@ -190,8 +191,22 @@
+
+
+
+
+
+ itemType="?itemType" downloadURL="?downloadURL"
+ state="?state" progress="?progress" status="?status"/>
diff --git a/mozilla/toolkit/mozapps/extensions/locale/extensions.dtd b/mozilla/toolkit/mozapps/extensions/locale/extensions.dtd
index a7e9e6bf966..c6a02cbdad5 100644
--- a/mozilla/toolkit/mozapps/extensions/locale/extensions.dtd
+++ b/mozilla/toolkit/mozapps/extensions/locale/extensions.dtd
@@ -46,6 +46,9 @@
+
+
+
diff --git a/mozilla/toolkit/mozapps/extensions/locale/extensions.properties b/mozilla/toolkit/mozapps/extensions/locale/extensions.properties
index 3144f9a1cf4..f8b5bdc3395 100644
--- a/mozilla/toolkit/mozapps/extensions/locale/extensions.properties
+++ b/mozilla/toolkit/mozapps/extensions/locale/extensions.properties
@@ -23,3 +23,9 @@ extensionsTitle=Extensions
globalItemList=The following items are available to all users. \nYou can start Firefox with -lock-item "{GUID}" to prevent users from uninstalling or disabling an item. To unlock an item, start Firefox with -unlock-item "{GUID}"
globalItemListExtensions=\n\nGlobally Available Extensions:\n==============================\n\n
globalItemListThemes=\n\nGlobally Available Themes:\n==========================\n\n
+
+installSuccess=Installed Successfully
+
+statusFormatKBKB=#1 of #2 KB
+statusFormatKBMB=#1 KB of #2 MB
+statusFormatMBMB=#1 of #2 MB
diff --git a/mozilla/toolkit/mozapps/extensions/public/nsIExtensionManager.idl b/mozilla/toolkit/mozapps/extensions/public/nsIExtensionManager.idl
index df811e2c242..488393ea448 100644
--- a/mozilla/toolkit/mozapps/extensions/public/nsIExtensionManager.idl
+++ b/mozilla/toolkit/mozapps/extensions/public/nsIExtensionManager.idl
@@ -42,6 +42,14 @@ interface nsIFile;
interface nsIRDFDataSource;
interface nsIUpdateItem;
+[scriptable, uuid(9048223f-ec50-49e5-9866-80ee8f26179d)]
+interface nsIExtensionDownloadProgressListener : nsISupports
+{
+ void onStateChange(in wstring aURL, in short aState, in long aValue);
+
+ void onProgress(in wstring aURL, in unsigned long aValue, in unsigned long aMaxValue);
+};
+
[scriptable, uuid(c3515b0f-99f4-453b-805e-1fdf5724d6d9)]
interface nsIExtensionManager : nsISupports
{
@@ -53,6 +61,12 @@ interface nsIExtensionManager : nsISupports
void enableExtension(in string aExtensionID);
void disableExtension(in string aExtensionID);
+ void addDownloads([array, size_is(aItemCount)] in nsIUpdateItem aItems,
+ in unsigned long aItemCount);
+ void removeDownload(in wstring aURL, in unsigned short aType);
+ long addDownloadObserver(in nsIExtensionDownloadProgressListener aObserver);
+ void removeDownloadObserverAt(in long aIndex);
+
void installTheme(in nsIFile aJARFile, in unsigned long aFlags);
void uninstallTheme(in string aThemeID);
diff --git a/mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in b/mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
index 7d344cac61f..55e0e3bf7e8 100644
--- a/mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
+++ b/mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
@@ -171,7 +171,7 @@ function getItemRoots(aItemType)
function getItemType(aURI)
{
- var type = 0;
+ var type = -1;
if (aURI.substr(0, PREFIX_EXTENSION.length) == PREFIX_EXTENSION)
type = nsIUpdateItem.TYPE_EXTENSION;
else if (aURI.substr(0, PREFIX_THEME.length) == PREFIX_THEME)
@@ -850,10 +850,12 @@ nsThemeInstaller.prototype = {
var elts = ctr.GetElements();
while (elts.hasMoreElements()) {
var elt = elts.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
- var name = chromeMetadata.GetTarget(elt, nameArc, true);
- name = name.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
-
- this._writer.installSkin(name, aIsProfile);
+ if (getItemType(elt.Value) != -1) {
+ var name = chromeMetadata.GetTarget(elt, nameArc, true);
+ name = name.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
+
+ this._writer.installSkin(name, aIsProfile);
+ }
}
this._writer.close();
@@ -1395,7 +1397,7 @@ nsExtensionManager.prototype = {
.createInstance(Components.interfaces.nsIZipReader);
zipReader.init(aXPIFile);
zipReader.open();
-
+
var installProfile = aFlags & nsIExtensionManager.FLAG_INSTALL_PROFILE;
var tempManifest = getFile(getDirKey(installProfile),
[DIR_EXTENSIONS, DIR_TEMP, FILE_INSTALL_MANIFEST]);
@@ -1604,6 +1606,90 @@ nsExtensionManager.prototype = {
return this._ds;
},
+ /////////////////////////////////////////////////////////////////////////////
+ // Downloads
+ _transactions: [],
+ addDownloads: function (aItems, aItemCount)
+ {
+ var txn = new nsItemDownloadTransaction(this);
+ for (var i = 0; i < aItemCount; ++i) {
+ var currItem = aItems[i];
+ txn.addDownload(currItem.name, currItem.updateURL, currItem.iconURL, currItem.type);
+ this._transactions.push(txn);
+ }
+
+ // Kick off the download process for this transaction
+ var os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Components.interfaces.nsIObserverService);
+ os.notifyObservers(txn, "xpinstall-progress", "open");
+ },
+
+ removeDownload: function (aURL, aType)
+ {
+ for (var i = 0; i < this._transactions.length; ++i) {
+ if (this._transactions[i].containsURL(aURL)) {
+ this._transactions[i].removeDownload(aURL, aType);
+ return;
+ }
+ }
+ },
+
+ // The nsIXPIProgressDialog implementation in the download transaction object
+ // forwards notifications through these methods which we then pass on to any
+ // front end objects implementing nsIExtensionDownloadProgressListener that
+ // are listening. We maintain the master state of download operations HERE,
+ // not in the front end, because if the user closes the extension or theme
+ // managers during the downloads we need to maintain state and not terminate
+ // the download/install process.
+ onStateChange: function (aTransaction, aURL, aState, aValue)
+ {
+ if (!(aURL in this._progressData))
+ this._progressData[aURL] = { };
+ this._progressData[aURL].state = aState;
+
+ for (var i = 0; i < this._downloadObservers.length; ++i)
+ this._downloadObservers[i].onStateChange(aURL, aState, aValue);
+
+ const nsIXPIProgressDialog = Components.interfaces.nsIXPIProgressDialog;
+ if (aState == nsIXPIProgressDialog.DIALOG_CLOSE) {
+ for (var i = 0; i < this._transactions.length; ++i) {
+ if (this._transactions[i] == aTransaction) {
+ this._transactions.splice(i, 1);
+ delete aTransaction;
+ break;
+ }
+ }
+ }
+ },
+
+ _progressData: { },
+ onProgress: function (aURL, aValue, aMaxValue)
+ {
+ for (var i = 0; i < this._downloadObservers.length; ++i)
+ this._downloadObservers[i].onProgress(aURL, aValue, aMaxValue);
+
+ if (!(aURL in this._progressData))
+ this._progressData[aURL] = { };
+ this._progressData[aURL].progress = Math.round((aValue / aMaxValue) * 100);
+ },
+
+ _downloadObservers: [],
+ addDownloadObserver: function (aXPIProgressDialog)
+ {
+ for (var i = 0; i < this._downloadObservers.length; ++i) {
+ if (this._downloadObservers[i] == aXPIProgressDialog)
+ return i;
+ }
+ this._downloadObservers.push(aXPIProgressDialog);
+ return this._downloadObservers.length - 1;
+ },
+
+ removeDownloadObserverAt: function (aIndex)
+ {
+ this._downloadObservers.splice(aIndex, 1);
+ this._ds.flushProgressInfo(this._progressData);
+ },
+
//
_ds: null,
@@ -1631,6 +1717,7 @@ nsExtensionManager.prototype = {
getInterfaces: function (aCount)
{
var interfaces = [Components.interfaces.nsIExtensionManager,
+ Components.interfaces.nsIXPIProgressDialog,
Components.interfaces.nsIObserver];
aCount.value = interfaces.length;
return interfaces;
@@ -1678,6 +1765,72 @@ nsExtensionManager.prototype = {
}
};
+///////////////////////////////////////////////////////////////////////////////
+//
+// nsItemDownloadTransaction
+//
+// This object implements nsIXPIProgressDialog and represents a collection of
+// XPI/JAR download and install operations. There is one
+// nsItemDownloadTransaction per back-end XPInstallManager object. We maintain
+// a collection of separate transaction objects because it's possible to have
+// multiple separate XPInstall download/install operations going on
+// simultaneously, each with its own XPInstallManager instance. For instance
+// you could start downloading two extensions and then download a theme. Each
+// of these operations would open the appropriate FE and have to be able to
+// track each operation independently.
+//
+function nsItemDownloadTransaction(aManager)
+{
+ this._manager = aManager;
+}
+
+nsItemDownloadTransaction.prototype = {
+ _manager : null,
+ _downloads : [],
+
+ addDownload: function (aName, aURL, aIconURL, aItemType)
+ {
+ this._downloads.push({ url: aURL, type: aItemType, waiting: true });
+ this._manager._ds.addDownload(aName, aURL, aIconURL, aItemType);
+ },
+
+ removeDownload: function (aURL, aItemType)
+ {
+ this._manager._ds.removeDownload(aURL, aItemType);
+ },
+
+ containsURL: function (aURL)
+ {
+ for (var i = 0; i < this._downloads.length; ++i) {
+ if (this._downloads[i].url == aURL)
+ return true;
+ }
+ return false;
+ },
+
+ /////////////////////////////////////////////////////////////////////////////
+ // nsIXPIProgressDialog
+ onStateChange: function (aIndex, aState, aValue)
+ {
+ this._manager.onStateChange(this, this._downloads[aIndex].url, aState, aValue);
+ },
+
+ onProgress: function (aIndex, aValue, aMaxValue)
+ {
+ this._manager.onProgress(this._downloads[aIndex].url, aValue, aMaxValue);
+ },
+
+ /////////////////////////////////////////////////////////////////////////////
+ // nsISupports
+ QueryInterface: function (aIID)
+ {
+ if (!aIID.equals(Components.interfaces.nsIXPIProgressDialog) &&
+ !aIID.equals(Components.interfaces.nsISupports))
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ return this;
+ }
+};
+
///////////////////////////////////////////////////////////////////////////////
//
// nsExtensionItemUpdater
@@ -1948,7 +2101,7 @@ nsExtensionsDataSource.prototype = {
var elements = ctr.GetElements();
while (elements.hasMoreElements()) {
var e = elements.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
- if (!this.isCompatible(this, e)) {
+ if (getItemType(e.Value) != -1 && !this.isCompatible(this, e)) {
var itemType = getItemType(e.Value);
var id = stripPrefix(e.Value, itemType);
var item = Components.classes["@mozilla.org/updates/item;1"]
@@ -1986,14 +2139,16 @@ nsExtensionsDataSource.prototype = {
var elements = ctr.GetElements();
while (elements.hasMoreElements()) {
var e = elements.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
- var id = stripPrefix(e.Value, aType);
- var item = Components.classes["@mozilla.org/updates/item;1"]
- .createInstance(Components.interfaces.nsIUpdateItem);
- item.init(id, this.getItemProperty(id, "version"),
- this.getItemProperty(id, "name"),
- -1, "", "",
- this.getItemProperty(id, "updateURL"), aType);
- items.push(item);
+ if (getItemType(e.Value) != -1) {
+ var id = stripPrefix(e.Value, aType);
+ var item = Components.classes["@mozilla.org/updates/item;1"]
+ .createInstance(Components.interfaces.nsIUpdateItem);
+ item.init(id, this.getItemProperty(id, "version"),
+ this.getItemProperty(id, "name"),
+ -1, "", "",
+ this.getItemProperty(id, "updateURL"), aType);
+ items.push(item);
+ }
}
}
}
@@ -2026,10 +2181,11 @@ nsExtensionsDataSource.prototype = {
var elements = ctr.GetElements();
while (elements.hasMoreElements()) {
var e = elements.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
-
- var value = this.GetTarget(e, this._emR(aFlag), true);
- if (!value)
- items.push(stripPrefix(e.Value, getItemType(e.Value)));
+ if (getItemType(e.Value) != -1) {
+ var value = this.GetTarget(e, this._emR(aFlag), true);
+ if (!value)
+ items.push(stripPrefix(e.Value, getItemType(e.Value)));
+ }
}
}
return items;
@@ -2264,22 +2420,81 @@ nsExtensionsDataSource.prototype = {
this.removeItemFromContainer(aThemeID, nsIUpdateItem.TYPE_THEME, isProfile);
},
+ // Cleans the resource of all its assertionss
removeItemMetadata: function (aItemID, aItemType)
{
var item = this._rdf.GetResource(getItemPrefix(aItemType) + aItemID);
var isProfile = this.isProfileItem(aItemID);
var ds = isProfile ? this._profileExtensions : this._appExtensions;
-
+ this._cleanResource(item, ds);
+ },
+
+ _cleanResource: function (aResource, aDS)
+ {
// Remove outward arcs
- var arcs = ds.ArcLabelsOut(item);
+ var arcs = aDS.ArcLabelsOut(aResource);
while (arcs.hasMoreElements()) {
var arc = arcs.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
- var value = ds.GetTarget(item, arc, true);
+ var value = aDS.GetTarget(aResource, arc, true);
if (value)
- ds.Unassert(item, arc, value);
+ aDS.Unassert(aResource, arc, value);
}
},
+ addDownload: function (aName, aURL, aIconURL, aItemType)
+ {
+ var root = this._rdf.GetResource(getItemRoot(aItemType));
+
+ var res = this._rdf.GetResource(aURL);
+ this._setProperty(this._profileExtensions, res,
+ this._emR("name"),
+ this._rdf.GetLiteral(aName))
+ this._setProperty(this._profileExtensions, res,
+ this._emR("version"),
+ this._rdf.GetLiteral(" "));
+ this._setProperty(this._profileExtensions, res,
+ this._emR("iconURL"),
+ this._rdf.GetLiteral(aIconURL));
+ this._setProperty(this._profileExtensions, res,
+ this._emR("downloadURL"),
+ this._rdf.GetLiteral(aURL));
+
+ var ctr = Components.classes["@mozilla.org/rdf/container;1"]
+ .createInstance(Components.interfaces.nsIRDFContainer);
+ ctr.Init(this._profileExtensions, root);
+ if (ctr.IndexOf(res) == -1)
+ ctr.InsertElementAt(res, 1, true);
+
+ this._flush(true);
+ },
+
+ removeDownload: function (aURL, aItemType)
+ {
+ var root = this._rdf.GetResource(getItemRoot(aItemType));
+ var res = this._rdf.GetResource(aURL);
+ var ctr = Components.classes["@mozilla.org/rdf/container;1"]
+ .createInstance(Components.interfaces.nsIRDFContainer);
+ ctr.Init(this._profileExtensions, root);
+ ctr.RemoveElement(res, true);
+ this._cleanResource(res, this._profileExtensions);
+
+ this._flush(true);
+ },
+
+ flushProgressInfo: function (aData)
+ {
+ for (var url in aData) {
+ var res = this._rdf.GetResource(url);
+ this._setProperty(this._profileExtensions, res,
+ this._emR("state"),
+ this._rdf.GetIntLiteral(aData[url].state));
+ this._setProperty(this._profileExtensions, res,
+ this._emR("progress"),
+ this._rdf.GetIntLiteral(aData[url].progress));
+ }
+ this._flush(true);
+ },
+
loadExtensions: function (aProfile)
{
var extensionsFile = getFile(getDirKey(aProfile),