зеркало из https://github.com/mozilla/gecko-dev.git
170006 downloading stuff
This commit is contained in:
Родитель
f3889c559f
Коммит
c62687dd9e
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -189,6 +189,111 @@
|
|||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="extension-waiting" extends="chrome://mozapps/content/shared/richview.xml#richview-item">
|
||||
<resources>
|
||||
<stylesheet src="chrome://mozapps/skin/extensions/extensions.css"/>
|
||||
</resources>
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="start">
|
||||
<xul:image class="extension-icon" xbl:inherits="src=image"
|
||||
style="width: 32px; max-width: 32px; height: 32px; max-height: 32px;"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox>
|
||||
<xul:label class="extension-item-name" xbl:inherits="value=name" crop="center"/>
|
||||
<xul:label class="extension-item-version" xbl:inherits="value=version"/>
|
||||
</xul:hbox>
|
||||
<xul:description class="extension-item-description">
|
||||
&extensionItem.waiting.label;
|
||||
</xul:description>
|
||||
<xul:label value=" "/>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
<implementation>
|
||||
<field name="eventPrefix">"extension-"</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="extension-downloading" extends="chrome://mozapps/content/shared/richview.xml#richview-item">
|
||||
<resources>
|
||||
<stylesheet src="chrome://mozapps/skin/extensions/extensions.css"/>
|
||||
</resources>
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="start">
|
||||
<xul:image class="extension-icon" xbl:inherits="src=image"
|
||||
style="width: 32px; max-width: 32px; height: 32px; max-height: 32px;"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox>
|
||||
<xul:label class="extension-item-name" xbl:inherits="value=name" crop="center"/>
|
||||
<xul:label class="extension-item-version" xbl:inherits="value=version"/>
|
||||
</xul:hbox>
|
||||
<xul:progressmeter class="extension-item-progress" xbl:inherits="value=progress"/>
|
||||
<xul:label class="extension-item-status" xbl:inherits="value=status"/>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
<implementation>
|
||||
<field name="eventPrefix">"extension-"</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="extension-installing" extends="chrome://mozapps/content/shared/richview.xml#richview-item">
|
||||
<resources>
|
||||
<stylesheet src="chrome://mozapps/skin/extensions/extensions.css"/>
|
||||
</resources>
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="start">
|
||||
<xul:image class="extension-icon" xbl:inherits="src=image"
|
||||
style="width: 32px; max-width: 32px; height: 32px; max-height: 32px;"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox>
|
||||
<xul:label class="extension-item-name" xbl:inherits="value=name" crop="center"/>
|
||||
<xul:label class="extension-item-version" xbl:inherits="value=version"/>
|
||||
</xul:hbox>
|
||||
<xul:description class="extension-item-description">
|
||||
&extensionItem.installing.label;
|
||||
</xul:description>
|
||||
<xul:label value=" "/>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
<implementation>
|
||||
<field name="eventPrefix">"extension-"</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="extension-done" extends="chrome://mozapps/content/shared/richview.xml#richview-item">
|
||||
<resources>
|
||||
<stylesheet src="chrome://mozapps/skin/extensions/extensions.css"/>
|
||||
</resources>
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="start">
|
||||
<xul:image class="extension-icon" xbl:inherits="src=image"
|
||||
style="width: 32px; max-width: 32px; height: 32px; max-height: 32px;"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox>
|
||||
<xul:label class="extension-item-name" xbl:inherits="value=name" crop="center"/>
|
||||
<xul:label class="extension-item-version" xbl:inherits="value=version"/>
|
||||
</xul:hbox>
|
||||
<xul:label class="extension-item-description" xbl:inherits="value=error"
|
||||
value="&extensionItem.done.label;"/>
|
||||
<xul:label value=" "/>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
<implementation>
|
||||
<field name="eventPrefix">"extension-"</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="theme" extends="chrome://mozapps/content/shared/richview.xml#richview-item">
|
||||
<resources>
|
||||
<stylesheet src="chrome://mozapps/skin/extensions/extensions.css"/>
|
||||
|
@ -213,5 +318,101 @@
|
|||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="theme-waiting" extends="chrome://mozapps/content/shared/richview.xml#richview-item">
|
||||
<resources>
|
||||
<stylesheet src="chrome://mozapps/skin/extensions/extensions.css"/>
|
||||
</resources>
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="start">
|
||||
<xul:image class="extension-icon" xbl:inherits="src=image"
|
||||
style="width: 32px; max-width: 32px; height: 32px; max-height: 32px;"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox>
|
||||
<xul:label class="extension-item-name" xbl:inherits="value=name" crop="center"/>
|
||||
<xul:label class="extension-item-version" xbl:inherits="value=version"/>
|
||||
</xul:hbox>
|
||||
<xul:label class="extension-item-status" crop="right">&extensionItem.waiting.label;</xul:label>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
<implementation>
|
||||
<field name="eventPrefix">"extension-"</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="theme-downloading" extends="chrome://mozapps/content/shared/richview.xml#richview-item">
|
||||
<resources>
|
||||
<stylesheet src="chrome://mozapps/skin/extensions/extensions.css"/>
|
||||
</resources>
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="start">
|
||||
<xul:image class="extension-icon" xbl:inherits="src=image"
|
||||
style="width: 32px; max-width: 32px; height: 32px; max-height: 32px;"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox>
|
||||
<xul:label class="extension-item-name" xbl:inherits="value=name" crop="center"/>
|
||||
<xul:label class="extension-item-version" xbl:inherits="value=version"/>
|
||||
</xul:hbox>
|
||||
<xul:progressmeter class="extension-item-progress" xbl:inherits="value=progress"/>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
<implementation>
|
||||
<field name="eventPrefix">"extension-"</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="theme-installing" extends="chrome://mozapps/content/shared/richview.xml#richview-item">
|
||||
<resources>
|
||||
<stylesheet src="chrome://mozapps/skin/extensions/extensions.css"/>
|
||||
</resources>
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="start">
|
||||
<xul:image class="extension-icon" xbl:inherits="src=image"
|
||||
style="width: 32px; max-width: 32px; height: 32px; max-height: 32px;"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox>
|
||||
<xul:label class="extension-item-name" xbl:inherits="value=name" crop="center"/>
|
||||
<xul:label class="extension-item-version" xbl:inherits="value=version"/>
|
||||
</xul:hbox>
|
||||
<xul:label class="extension-item-status" crop="right">&extensionItem.installing.label;</xul:label>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
<implementation>
|
||||
<field name="eventPrefix">"extension-"</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="theme-done" extends="chrome://mozapps/content/shared/richview.xml#richview-item">
|
||||
<resources>
|
||||
<stylesheet src="chrome://mozapps/skin/extensions/extensions.css"/>
|
||||
</resources>
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="start">
|
||||
<xul:image class="extension-icon" xbl:inherits="src=image"
|
||||
style="width: 32px; max-width: 32px; height: 32px; max-height: 32px;"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox>
|
||||
<xul:label class="extension-item-name" xbl:inherits="value=name" crop="center"/>
|
||||
<xul:label class="extension-item-version" xbl:inherits="value=version"/>
|
||||
</xul:hbox>
|
||||
<xul:label class="extension-item-status" crop="right">&extensionItem.done.label;</xul:label>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
<implementation>
|
||||
<field name="eventPrefix">"extension-"</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
<stringbundleset id="extensionsSet">
|
||||
<stringbundle id="brandStrings" src="chrome://global/locale/brand.properties"/>
|
||||
<stringbundle id="extensionsStrings" src="chrome://mozapps/locale/extensions/extensions.properties"/>
|
||||
<stringbundle id="xpinstallStrings" src="chrome://communicator/locale/xpinstall/xpinstall.properties"/>
|
||||
</stringbundleset>
|
||||
|
||||
<keyset id="extensionsKeys">
|
||||
|
@ -190,8 +191,22 @@
|
|||
<binding subject="?extension"
|
||||
predicate="http://www.mozilla.org/2004/em-rdf#internalName"
|
||||
object="?internalName"/>
|
||||
<binding subject="?extension"
|
||||
predicate="http://www.mozilla.org/2004/em-rdf#downloadURL"
|
||||
object="?downloadURL"/>
|
||||
<binding subject="?extension"
|
||||
predicate="http://www.mozilla.org/2004/em-rdf#state"
|
||||
object="?state"/>
|
||||
<binding subject="?extension"
|
||||
predicate="http://www.mozilla.org/2004/em-rdf#progress"
|
||||
object="?progress"/>
|
||||
<binding subject="?extension"
|
||||
predicate="http://www.mozilla.org/2004/em-rdf#status"
|
||||
object="?status"/>
|
||||
</bindings>
|
||||
<action>
|
||||
<!-- XXXben - we could really use a variety of different templates
|
||||
here to make each element not be so heavy. -->
|
||||
<extension uri="?extension" context="extensionContextMenu"
|
||||
image="?icon" name="?name" version="?version"
|
||||
description="?description" creator="?creator"
|
||||
|
@ -201,7 +216,8 @@
|
|||
previewImage="?previewImage" internalName="?internalName"
|
||||
toBeInstalled="?toBeInstalled" toBeUninstalled="?toBeUninstalled"
|
||||
toBeEnabled="?toBeEnabled" toBeDisabled="?toBeDisabled"
|
||||
itemType="?itemType"/>
|
||||
itemType="?itemType" downloadURL="?downloadURL"
|
||||
state="?state" progress="?progress" status="?status"/>
|
||||
</action>
|
||||
</rule>
|
||||
</template>
|
||||
|
|
|
@ -46,6 +46,9 @@
|
|||
<!ENTITY extensionItem.toBeEnabled.label "This item will be enabled after you restart &brandShortName;.">
|
||||
<!ENTITY extensionItem.toBeInstalled.label "This item will be installed after you restart &brandShortName;.">
|
||||
<!ENTITY extensionItem.toBeUninstalled.label "This item will be uninstalled after you restart &brandShortName;.">
|
||||
<!ENTITY extensionItem.done.label "Install Success">
|
||||
<!ENTITY extensionItem.waiting.label "Waiting...">
|
||||
<!ENTITY extensionItem.installing.label "Installing...">
|
||||
|
||||
<!ENTITY getMoreExtensions.label "Get More Extensions">
|
||||
<!ENTITY getMoreExtensions.tooltip "Get More Extensions from update.mozilla.org">
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,11 +850,13 @@ nsThemeInstaller.prototype = {
|
|||
var elts = ctr.GetElements();
|
||||
while (elts.hasMoreElements()) {
|
||||
var elt = elts.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
|
||||
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();
|
||||
|
||||
|
@ -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,6 +2139,7 @@ nsExtensionsDataSource.prototype = {
|
|||
var elements = ctr.GetElements();
|
||||
while (elements.hasMoreElements()) {
|
||||
var e = elements.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
|
||||
if (getItemType(e.Value) != -1) {
|
||||
var id = stripPrefix(e.Value, aType);
|
||||
var item = Components.classes["@mozilla.org/updates/item;1"]
|
||||
.createInstance(Components.interfaces.nsIUpdateItem);
|
||||
|
@ -1997,6 +2151,7 @@ nsExtensionsDataSource.prototype = {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
aCountRef.value = items.length;
|
||||
return items;
|
||||
},
|
||||
|
@ -2026,12 +2181,13 @@ nsExtensionsDataSource.prototype = {
|
|||
var elements = ctr.GetElements();
|
||||
while (elements.hasMoreElements()) {
|
||||
var e = elements.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
|
||||
|
||||
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),
|
||||
|
|
Загрузка…
Ссылка в новой задаче