зеркало из https://github.com/mozilla/pjs.git
generic version checking service, support custom update urls
This commit is contained in:
Родитель
ab8ff1f170
Коммит
3d5ea95a77
|
@ -91,7 +91,7 @@ nsInstallLogBase.prototype = {
|
|||
//
|
||||
function nsInstallLogWriter(aExtensionID, aIsProfile)
|
||||
{
|
||||
this._isProfile = aIsProfile; // XXXben
|
||||
this._isProfile = aIsProfile;
|
||||
this._uninstallLog = getDir(aIsProfile ? "ProfD" : "ProfD",
|
||||
["extensions", aExtensionID, "uninstall"]); // XXXben XCurProcDir
|
||||
this._uninstallLog.append("uninstall.log");
|
||||
|
@ -137,7 +137,7 @@ nsInstallLogWriter.prototype = {
|
|||
//
|
||||
function nsInstallLogReader(aExtensionID, aIsProfile, aListener)
|
||||
{
|
||||
this._isProfile = aIsProfile; // XXXben
|
||||
this._isProfile = aIsProfile;
|
||||
this.uninstallLog = getDir(aIsProfile ? "ProfD" : "ProfD",
|
||||
["extensions", aExtensionID, "uninstall"]); // XXXben XCurProcDir
|
||||
this.uninstallLog.append("uninstall.log");
|
||||
|
@ -357,7 +357,7 @@ nsExtensionInstaller.prototype = {
|
|||
type = this._writer.CHROME_TYPE_PACKAGE;
|
||||
}
|
||||
else if (aChromeType.EqualsNode(this._provTypeSkin)) {
|
||||
cr.installSkin(fileURL, this._isProfile);
|
||||
cr.installSkin(fileURL, this._isProfile, true); // Extension skins can execute scripts
|
||||
type = this._writer.CHROME_TYPE_SKIN;
|
||||
}
|
||||
else if (aChromeType.EqualsNode(this._provTypeLocale)) {
|
||||
|
@ -382,6 +382,10 @@ nsExtensionInstaller.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// nsExtensionUninstaller
|
||||
//
|
||||
function nsExtensionUninstaller(aExtensionDS)
|
||||
{
|
||||
this._cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"]
|
||||
|
@ -460,154 +464,6 @@ nsExtensionUninstaller.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// nsVersionChecker
|
||||
//
|
||||
function VersionChecker(aExtensionResource, aAppID, aAppVersion, aDataSource)
|
||||
{
|
||||
this._extensionResource = aExtensionResource;
|
||||
this._appID = aAppID;
|
||||
this._appVersion = aAppVersion;
|
||||
this._ds = aDataSource;
|
||||
}
|
||||
|
||||
VersionChecker.prototype = {
|
||||
get isCompatible ()
|
||||
{
|
||||
var targets = this._ds.GetTargets(this._extensionResource, this._ds._emR("targetApplication"), true);
|
||||
while (targets.hasMoreElements()) {
|
||||
var targetAppString = targets.getNext().QueryInterface(Components.interfaces.nsIRDFLiteral);
|
||||
|
||||
var versionParts = targetAppString.Value.split(",");
|
||||
if (versionParts[0] == this._appID) {
|
||||
var minRequiredVersionStr = versionParts[1];
|
||||
var maxRequiredVersionStr = versionParts[2];
|
||||
var power = this._getLargestPower([this._appVersion,
|
||||
minRequiredVersionStr,
|
||||
maxRequiredVersionStr]);
|
||||
var minRequiredVersion = this._parseVersion(minRequiredVersionStr, power);
|
||||
var maxRequiredVersion = this._parseVersion(maxRequiredVersionStr, power);
|
||||
var appVersion = this._parseVersion(this._appVersion, power);
|
||||
|
||||
return (appVersion >= minRequiredVersion &&
|
||||
appVersion <= maxRequiredVersion);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// Convert a version string into an integer value
|
||||
_parseVersion: function (aVersion, aPower)
|
||||
{
|
||||
var parts = aVersion.split(".");
|
||||
var version = 0;
|
||||
if (aPower == 0)
|
||||
aPower = parts.length;
|
||||
|
||||
for (var i = 0; i < parts.length; ++i) {
|
||||
var token = parts[i];
|
||||
if (token.charAt(token.length-1) == "+") {
|
||||
token = token.substr(0, token.lastIndexOf("+"));
|
||||
version += 1;
|
||||
if (token.length == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
version += parseInt(token) * Math.pow(10, aPower - i);
|
||||
}
|
||||
return version;
|
||||
},
|
||||
|
||||
_parsePower: function (aVersion)
|
||||
{
|
||||
return aVersion.split(".").length;
|
||||
},
|
||||
|
||||
_getLargestPower: function (aVersionArray)
|
||||
{
|
||||
var biggestPower = 0;
|
||||
for (var i = 0; i < aVersionArray.length; ++i) {
|
||||
var power = this._parsePower(aVersionArray[i]);
|
||||
if (power > biggestPower)
|
||||
biggestPower = power;
|
||||
}
|
||||
return biggestPower;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// nsJarFileExtractor
|
||||
//
|
||||
function nsJarFileExtractor(aXPIFile, aTargetDir)
|
||||
{
|
||||
this._xpiFile = aXPIFile.path;
|
||||
this._targetDir = aTargetDir.path;
|
||||
// this._proxyObject(Components, Components.interfaces.nsIXPCComponents, "_components");
|
||||
/*
|
||||
this._proxyObject(aXPIFile, Components.interfaces.nsIFile, "_xpiFile");
|
||||
this._proxyObject(aTargetDir, Components.interfaces.nsIFile, "_targetDir");
|
||||
*/
|
||||
}
|
||||
|
||||
nsJarFileExtractor.prototype = {
|
||||
// proxied objects
|
||||
_xpiFile: null,
|
||||
_targetDir: null,
|
||||
_components: null,
|
||||
|
||||
_proxyObject: function (aObject, aIID, aTarget)
|
||||
{
|
||||
const nsIEventQueueService = Components.interfaces.nsIEventQueueService;
|
||||
var eqService = Components.classes["@mozilla.org/event-queue-service;1"]
|
||||
.getService(nsIEventQueueService);
|
||||
var uiQ = eqService.getSpecialEventQueue(nsIEventQueueService.UI_THREAD_EVENT_QUEUE);
|
||||
|
||||
var proxyObjectManager = Components.classes["@mozilla.org/xpcomproxy;1"]
|
||||
.getService(Components.interfaces.nsIProxyObjectManager);
|
||||
const PROXY_SYNC = 0x01;
|
||||
const PROXY_ALWAYS = 0x04;
|
||||
this[aTarget] = proxyObjectManager.getProxyForObject(uiQ, aIID, aObject,
|
||||
PROXY_SYNC | PROXY_ALWAYS);
|
||||
},
|
||||
|
||||
extract: function ()
|
||||
{
|
||||
const nsIThread = Components.interfaces.nsIThread;
|
||||
var thread = Components.classes["@mozilla.org/thread;1"]
|
||||
.createInstance(nsIThread);
|
||||
thread.init(this, 0, nsIThread.PRIORITY_NORMAL,
|
||||
nsIThread.SCOPE_GLOBAL,
|
||||
nsIThread.STATE_JOINABLE);
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsIRunnable
|
||||
run: function ()
|
||||
{
|
||||
dump("*** RUNNING THREAD\n");
|
||||
/*
|
||||
var xpiFile = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
xpiFile.initWithPath(this._xpiFile);
|
||||
var targetDir = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
targetDir.initWithPath(this._targetDir);
|
||||
|
||||
var zipReader = Components.classes["@mozilla.org/libjar/zip-reader;1"]
|
||||
.createInstance(Components.interfaces.nsIZipReader);
|
||||
zipReader.init(xpiFile);
|
||||
|
||||
var entries = zipReader.findEntries("*");
|
||||
while (entries.hasMoreElements()) {
|
||||
var entry = entries.getNext().QueryInterface(Components.interfaces.nsIZipEntry);
|
||||
dump("*** zip entry = " + entry.name + "\n");
|
||||
}
|
||||
*/
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// nsExtensionManager
|
||||
|
@ -910,9 +766,12 @@ nsExtensionManager.prototype = {
|
|||
.getService(Components.interfaces.nsIRDFService);
|
||||
var manifestRoot = rdf.GetResource("urn:mozilla:extension:manifest");
|
||||
var id = rdf.GetResource(EM_NS("id"));
|
||||
// XXXben - do version check
|
||||
var idLiteral = aDataSource.GetTarget(manifestRoot, id, true);
|
||||
return idLiteral.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
||||
// Check the target application range specified by the extension metadata.
|
||||
if (this._ds.isCompatible(aDataSource, id)) {
|
||||
var idLiteral = aDataSource.GetTarget(manifestRoot, id, true);
|
||||
return idLiteral.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
_stageExtensionXPI: function (aZipReader, aExtensionID, aInstallProfile)
|
||||
|
@ -1042,6 +901,10 @@ nsExtensionManager.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// nsExtensionItemUpdater
|
||||
//
|
||||
function nsExtensionItemUpdater(aItems, aTargetAppID, aTargetAppVersion)
|
||||
{
|
||||
this._items = aItems;
|
||||
|
@ -1069,6 +932,27 @@ nsExtensionItemUpdater.prototype = {
|
|||
var wsdlURI = pref.getComplexValue(PREF_UPDATE_EXT_WSDL_URI,
|
||||
Components.interfaces.nsIPrefLocalizedString).data;
|
||||
wspFactory.createProxyAsync(wsdlURI, "VersionCheck", "", true, this);
|
||||
|
||||
for (var i = 0; i < this._items.length; ++i) {
|
||||
var e = this._items[i];
|
||||
if (e.updateRDF) {
|
||||
var dsURI = e.updateRDF;
|
||||
dsURI = dsURI.replace(/%ITEM_ID%/g, e.id);
|
||||
dsURI = dsURI.replace(/%ITEM_VERSION%/g, e.version);
|
||||
dsURI = dsURI.replace(/%APP_ID%/g, this._appID);
|
||||
dsURI = dsURI.replace(/%APP_VERSION%/g, this._appVersion);
|
||||
var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
|
||||
.getService(Components.interfaces.nsIRDFService);
|
||||
var ds = rdf.GetDataSource(dsURI);
|
||||
var rds = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource)
|
||||
if (rds.loaded)
|
||||
this.onDatasourceLoaded(ds);
|
||||
else {
|
||||
var sink = ds.QueryInterface(Components.interfaces.nsIRDFXMLSink);
|
||||
sink.addXMLSinkObserver(new nsExtensionUpdateXMLRDFDSObserver(this, e));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1079,8 +963,10 @@ nsExtensionItemUpdater.prototype = {
|
|||
{
|
||||
for (var i = 0; i < this._items.length; ++i) {
|
||||
var e = this._items[i];
|
||||
this._os.notifyObservers(null, "Update:Extension:Item-Started", e.name + " " + e.version);
|
||||
this._proxy.getNewestExtension(eval(e.objectSource), this._appID, this._appVersion);
|
||||
if (!e.updateRDF) {
|
||||
this._os.notifyObservers(null, "Update:Extension:Item-Started", e.name + " " + e.version);
|
||||
this._proxy.getNewestExtension(eval(e.objectSource), this._appID, this._appVersion);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1098,20 +984,69 @@ nsExtensionItemUpdater.prototype = {
|
|||
this._os.notifyObservers(aResult, "Update:Extension:Item-Error", aMessage);
|
||||
},
|
||||
|
||||
onDatasourceLoaded: function (aDatasource, aExtension)
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The extension update RDF file looks something like this:
|
||||
// <RDF:Description about="urn:mozilla:extension:{EXTENSION GUID}">
|
||||
// <em:version>5.0</em:version>
|
||||
// <em:updateLink><XPI URL></em:updateLink>
|
||||
// </RDF:Description>
|
||||
|
||||
// Parse the response RDF
|
||||
var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
|
||||
.getService(Components.interfaces.nsIRDFService);
|
||||
var versionArc = rdf.GetResource(EM_NS("version"));
|
||||
var updateLinkArc = rdf.GetResource(EM_NS("updateLink"));
|
||||
var extensionRes = rdf.GetResource("urn:mozilla:extension:" + aExtension.id);
|
||||
|
||||
var version = aDatasource.GetTarget(extensionRes, versionArc, true);
|
||||
version = version.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
||||
var updateLink = aDatasource.GetTarget(extensionRes, updateLinkArc, true);
|
||||
updateLink = updateLink.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
||||
|
||||
// Check to see if this is a newer version.
|
||||
var versionChecker = Components.classes["@mozilla.org/updates/version-checker;1"]
|
||||
.getService(Components.interfaces.nsIVersionChecker);
|
||||
if (versionChecker.compare(aExtension.version, version) < 0) {
|
||||
// Construct an update item and pass it to observers.
|
||||
var item = Components.classes["@mozilla.org/updates/item;1"]
|
||||
.createInstance(Components.interfaces.nsIUpdateItem);
|
||||
item.init(aExtension.id, version, aExtension.name, -1, updateLink, "", "",
|
||||
Components.interfaces.TYPE_EXTENSION); // XXXben
|
||||
this._os.notifyObservers(item, "Update:Extension:Item-Ended", "");
|
||||
++this._updateCount;
|
||||
}
|
||||
|
||||
this._checkForDone();
|
||||
},
|
||||
|
||||
onDatasourceError: function (aExtension)
|
||||
{
|
||||
// XXXben - some way of indicating an error in the update process
|
||||
this._checkForDone();
|
||||
},
|
||||
|
||||
getNewestExtensionCallback: function (aResult)
|
||||
{
|
||||
var item = aResult;
|
||||
dump("*** result = " + item.toSource() + "\n");
|
||||
try {
|
||||
item.name.toString(); // XXXben This is a lame hack to cause an exception to be
|
||||
// thrown for null values when there is no newer extension
|
||||
// or something else bad happens on the server that we
|
||||
// don't recognize.
|
||||
this._os.notifyObservers(aResult, "Update:Extension:Item-Ended", "goat");
|
||||
this._os.notifyObservers(aResult, "Update:Extension:Item-Ended", "");
|
||||
++this._updateCount;
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
|
||||
this._checkForDone();
|
||||
},
|
||||
|
||||
_checkForDone: function ()
|
||||
{
|
||||
if (--this._count == 0) {
|
||||
var pref = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
|
@ -1132,6 +1067,50 @@ nsExtensionItemUpdater.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
function nsExtensionUpdateXMLRDFDSObserver(aUpdater, aExtension)
|
||||
{
|
||||
this._updater = aUpdater;
|
||||
this._extension = aExtension;
|
||||
}
|
||||
|
||||
nsExtensionUpdateXMLRDFDSObserver.prototype =
|
||||
{
|
||||
_updater : null,
|
||||
_extension : null,
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFXMLSinkObserver
|
||||
onBeginLoad: function(aSink)
|
||||
{
|
||||
},
|
||||
onInterrupt: function(aSink)
|
||||
{
|
||||
},
|
||||
onResume: function(aSink)
|
||||
{
|
||||
},
|
||||
|
||||
onEndLoad: function(aSink)
|
||||
{
|
||||
aSink.removeXMLSinkObserver(this);
|
||||
|
||||
var ds = aSink.QueryInterface(Components.interfaces.nsIRDFDataSource);
|
||||
this._updater.onDatasourceLoaded(ds, this._extension);
|
||||
},
|
||||
|
||||
onError: function(aSink, aStatus, aErrorMsg)
|
||||
{
|
||||
aSink.removeXMLSinkObserver(this);
|
||||
|
||||
this._updater.onDatasourceError(this._extension);
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// nsExtensionsDataSource
|
||||
//
|
||||
function nsExtensionsDataSource()
|
||||
{
|
||||
this._rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
|
||||
|
@ -1160,6 +1139,29 @@ nsExtensionsDataSource.prototype = {
|
|||
{
|
||||
return aResourceURI.substr("urn:mozilla:extension:".length, aResourceURI.length);
|
||||
},
|
||||
|
||||
isCompatible: function (aDS, aExtensionID)
|
||||
{
|
||||
var r = this._rdf.GetResource("urn:mozilla:extension:" + aExtensionID);
|
||||
var targets = aDS.GetTargets(r, this._emR("targetApplication"), true);
|
||||
|
||||
var pref = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
var appVersion = pref.getCharPref(PREF_EM_APP_VERSION);
|
||||
var appID = pref.getCharPref(PREF_EM_APP_ID);
|
||||
while (targets.hasMoreElements()) {
|
||||
var targetApp = targets.getNext().QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
||||
|
||||
var versionParts = targetApp.split(",");
|
||||
if (versionParts[0] == appID) {
|
||||
var versionChecker = Components.classes["@mozilla.org/updates/version-checker;1"]
|
||||
.getService(Components.interfaces.nsIVersionChecker);
|
||||
return ((versionChecker.compare(appVersion, versionParts[1]) >= 0) &&
|
||||
(versionChecker.compare(appVersion, versionParts[2]) <= 0));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
getIncompatibleItemList: function (aAppID, aAppVersion)
|
||||
{
|
||||
|
@ -1172,14 +1174,13 @@ nsExtensionsDataSource.prototype = {
|
|||
var elements = ctr.GetElements();
|
||||
while (elements.hasMoreElements()) {
|
||||
var e = elements.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
|
||||
var checker = new VersionChecker(e, aAppID, aAppVersion, this);
|
||||
if (!checker.isCompatible) {
|
||||
var id = this._stripPrefix(e.Value);
|
||||
var id = this._stripPrefix(e.Value);
|
||||
if (!this.isCompatible(this, id)) {
|
||||
var item = Components.classes["@mozilla.org/updates/item;1"]
|
||||
.createInstance(Components.interfaces.nsIUpdateItem);
|
||||
item.init(id, this.getExtensionProperty(id, "version"),
|
||||
this.getExtensionProperty(id, "name"),
|
||||
-1, "", "",
|
||||
-1, "", "", this.getExtensionProperty(id, "updateURL"),
|
||||
Components.interfaces.nsIUpdateItem.TYPE_EXTENSION); // XXXben
|
||||
items.push(item);
|
||||
}
|
||||
|
@ -1195,7 +1196,8 @@ nsExtensionsDataSource.prototype = {
|
|||
.createInstance(Components.interfaces.nsIUpdateItem);
|
||||
item.init(aItemID, this.getExtensionProperty(aItemID, "version"),
|
||||
this.getExtensionProperty(aItemID, "name"),
|
||||
-1, "", "", aType);
|
||||
-1, "", "", this.getExtensionProperty(aItemID, "updateURL"),
|
||||
aType);
|
||||
items.push(item);
|
||||
}
|
||||
else {
|
||||
|
@ -1211,7 +1213,8 @@ nsExtensionsDataSource.prototype = {
|
|||
.createInstance(Components.interfaces.nsIUpdateItem);
|
||||
item.init(id, this.getExtensionProperty(id, "version"),
|
||||
this.getExtensionProperty(id, "name"),
|
||||
-1, "", "", aType);
|
||||
-1, "", "",
|
||||
this.getExtensionProperty(id, "updateURL"), aType);
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
|
@ -1351,11 +1354,28 @@ nsExtensionsDataSource.prototype = {
|
|||
var extension = this._rdf.GetResource("urn:mozilla:extension:" + aExtensionID);
|
||||
ctr.RemoveElement(extension, true);
|
||||
|
||||
// Clean the extension resource
|
||||
this._removeExtensionMetadata(aExtensionID);
|
||||
|
||||
this.setExtensionProperty(aExtensionID, this._emR("toBeUninstalled"),
|
||||
this._emL("true"),
|
||||
this.isProfileExtension(aExtensionID));
|
||||
},
|
||||
|
||||
_removeExtensionMetadata: function (aExtensionID)
|
||||
{
|
||||
var extension = this._rdf.GetResource("urn:mozilla:extension:" + aExtensionID);
|
||||
var isProfile = this.isProfileExtension(aExtensionID);
|
||||
var ds = isProfile ? this._profileExtensions : this._appExtensions;
|
||||
var arcs = ds.ArcLabelsOut(extension);
|
||||
while (arcs.hasMoreElements()) {
|
||||
var arc = arcs.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
|
||||
var value = ds.GetTarget(extension, arc, true);
|
||||
if (value)
|
||||
ds.Unassert(extension, arc, value);
|
||||
}
|
||||
},
|
||||
|
||||
loadExtensions: function (aProfile)
|
||||
{
|
||||
var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
|
||||
|
|
|
@ -1,173 +0,0 @@
|
|||
// XXXben - this is not used by anything, it's just a backup of some code I did have in nsExtensionManager.js.in
|
||||
|
||||
function nsExtensionUpdater2(aExtensions,
|
||||
aTargetAppID, aTargetAppVersion)
|
||||
{
|
||||
this._extensions = aExtensions;
|
||||
this._count = aExtensions.length;
|
||||
this._appID = aTargetAppID;
|
||||
this._appVersion = aTargetAppVersion;
|
||||
|
||||
this._os = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
}
|
||||
|
||||
nsExtensionUpdater2.prototype = {
|
||||
_extensionSchemaType: null,
|
||||
loadSchema: function ()
|
||||
{
|
||||
function SchemaLoaderListener(aUpdater)
|
||||
{
|
||||
this._updater = aUpdater;
|
||||
}
|
||||
|
||||
SchemaLoaderListener.prototype = {
|
||||
onLoad: function (aSchema)
|
||||
{
|
||||
dump("*** schema loaded = " + aSchema + "\n");
|
||||
var count = aSchema.typeCount;
|
||||
for (var i = 0; i < count; ++i) {
|
||||
var type = aSchema.getTypeByIndex(i);
|
||||
dump("*** schema type = " + type.name + "\n");
|
||||
}
|
||||
|
||||
this._updater._extensionSchemaType = aSchema.getTypeByName("Extension");
|
||||
|
||||
this._updater._schemaLoaded();
|
||||
},
|
||||
|
||||
onError: function (aStatus, aMessage)
|
||||
{
|
||||
dump("*** schema load error " + aStatus + ", msg = " + aMessage + "\n");
|
||||
}
|
||||
};
|
||||
|
||||
var schemaLoader = Components.classes["@mozilla.org/xmlextras/schemas/schemaloader;1"]
|
||||
.createInstance(Components.interfaces.nsISchemaLoader);
|
||||
var schemaLoaderListener = new SchemaLoaderListener(this);
|
||||
schemaLoader.loadAsync("http://www.bengoodger.com/software/mb/umo/types.xsd",
|
||||
schemaLoaderListener);
|
||||
},
|
||||
|
||||
_schemaLoaded: function ()
|
||||
{
|
||||
var call = Components.classes["@mozilla.org/xmlextras/soap/call;1"]
|
||||
.createInstance(Components.interfaces.nsISOAPCall);
|
||||
call.transportURI = "http://localhost:8080/axis/services/VersionCheck";
|
||||
|
||||
for (var i = 0; i < this._extensions.length; ++i) {
|
||||
var e = this._extensions[i];
|
||||
|
||||
var params = [this._createParam("in0", e, this._extensionSchemaType),
|
||||
this._createParam("in1", this._appID, null),
|
||||
this._createParam("in2", this._appVersion, null)];
|
||||
call.encode(0, "getNewestExtension", "urn:VersionCheck", 0, null, params.length, params);
|
||||
var response = call.invoke();
|
||||
dump("*** response = " + response + "\n");
|
||||
var count = { };
|
||||
var params;
|
||||
response.getParameters(false, count, params);
|
||||
dump("*** params = " + count.value + "\n");
|
||||
for (var j = 0; j < count.value; ++j) {
|
||||
var param = params[j];
|
||||
dump("*** param = " + param.name + ", parm = " + param + ", element = " + param.element + ", value = " + param.value + "\n");
|
||||
// var v = param.value.QueryInterface(Components.interfaces.nsIVariant);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_walkKids: function (e)
|
||||
{
|
||||
for (var i = 0; i < e.childNodes.length; ++i) {
|
||||
var kid = e.childNodes[i];
|
||||
dump("<" + kid.nodeName);
|
||||
for (var k = 0; k < kid.attributes.length; ++k)
|
||||
dump(" " + kid.attributes[k] + "=" + kid.getAttribute(kid.attributes[k]));
|
||||
if (kid.hasChildNodes()) {
|
||||
this._walkKids(kid);
|
||||
dump("</" + kid.nodeName);
|
||||
}
|
||||
else
|
||||
dump(">");
|
||||
}
|
||||
},
|
||||
|
||||
_createParam: function (aParamName, aParamValue, aParamSchemaType)
|
||||
{
|
||||
var param = Components.classes["@mozilla.org/xmlextras/soap/parameter;1"]
|
||||
.createInstance(Components.interfaces.nsISOAPParameter);
|
||||
param.name = aParamName;
|
||||
param.namespaceURI = "urn:VersionCheck";
|
||||
if (aParamSchemaType)
|
||||
param.schemaType = aParamSchemaType;
|
||||
param.value = aParamValue;
|
||||
return param;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
||||
// this will come back later when we do custom update urls
|
||||
getUpdateURLs: function (aExtensionID)
|
||||
{
|
||||
var pref = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
var appID = pref.getCharPref(PREF_EM_APP_ID);
|
||||
|
||||
var urls = [];
|
||||
if (aExtensionID) {
|
||||
var updateURL = this._getUpdateURLInternal(aExtensionID);
|
||||
updateURL = updateURL.replace(/%APP%/g, escape(appID));
|
||||
updateURL = updateURL.replace(/%ITEM%/g, escape(aExtensionID));
|
||||
urls.push(updateURL);
|
||||
}
|
||||
else {
|
||||
var ctr = Components.classes["@mozilla.org/rdf/container;1"]
|
||||
.createInstance(Components.interfaces.nsIRDFContainer);
|
||||
ctr.Init(this, this._rdf.GetResource("urn:mozilla:extension:root"));
|
||||
|
||||
var urlHash = { };
|
||||
|
||||
var e = ctr.GetElements();
|
||||
while (e.hasMoreElements()) {
|
||||
var r = e.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
|
||||
var extensionID = r.Value.substr("urn:mozilla:extension:".length, r.Value.length);
|
||||
var updateURL = this._getUpdateURLInternal(extensionID);
|
||||
if (!(updateURL in urlHash))
|
||||
urlHash[updateURL] = [];
|
||||
|
||||
urlHash[updateURL].push(extensionID);
|
||||
}
|
||||
|
||||
for (var url in urlHash) {
|
||||
var guidString = "";
|
||||
var urlCount = urlHash[url].length;
|
||||
for (var i = 0; i < urlCount; ++i)
|
||||
guidString += escape(urlHash[url][i] + (i < urlCount - 1 ? "," : ""));
|
||||
url = url.replace(/%APP%/g, appID);
|
||||
url = url.replace(/%ITEM%/g, guidString);
|
||||
urls.push(url);
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
},
|
||||
|
||||
_getUpdateURLInternal: function (aExtensionID)
|
||||
{
|
||||
var updateURL;
|
||||
var extension = this._rdf.GetResource("urn:mozilla:extension:" + aExtensionID);
|
||||
|
||||
if (this.hasArcOut(extension, this._emR("updateURL"))) {
|
||||
updateURL = this.GetTarget(extension, this._emR("updateURL"), true);
|
||||
if (updateURL)
|
||||
updateURL = updateURL.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
||||
}
|
||||
|
||||
if (!updateURL) {
|
||||
var pref = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
updateURL = pref.getCharPref(PREF_EM_DEFAULTUPDATEURL);
|
||||
}
|
||||
return updateURL;
|
||||
},
|
||||
|
|
@ -45,6 +45,7 @@ const nsIExtensionManager = Components.interfaces.nsIExtensionMana
|
|||
|
||||
const PREF_APP_ID = "app.id";
|
||||
const PREF_UPDATE_APP_UPDATESAVAILABLE = "update.app.updatesAvailable";
|
||||
const PREF_UPDATE_EXTENSIONS_ENABLED = "update.extensions.enabled";
|
||||
|
||||
var gSourceEvent = null;
|
||||
var gUpdateTypes = null;
|
||||
|
@ -74,7 +75,7 @@ var gUpdateWizard = {
|
|||
var pref = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
this.shouldSuggestAutoChecking = (gSourceEvent == nsIUpdateService.SOURCE_EVENT_MISMATCH) &&
|
||||
!pref.getBoolPref("update.extensions.enabled");
|
||||
!pref.getBoolPref(PREF_UPDATE_EXTENSIONS_ENABLED);
|
||||
|
||||
if (gSourceEvent == nsIUpdateService.SOURCE_EVENT_USER) {
|
||||
document.getElementById("mismatch").setAttribute("next", "checking");
|
||||
|
@ -262,7 +263,7 @@ var gUpdatePage = {
|
|||
item.init(appID, updates.appUpdateVersion,
|
||||
brandShortName, -1, updates.appUpdateURL,
|
||||
"chrome://mozapps/skin/update/icon32.png",
|
||||
nsIUpdateItem.TYPE_APP);
|
||||
"", nsIUpdateItem.TYPE_APP);
|
||||
gUpdateWizard.itemsToUpdate.splice(0, 0, item);
|
||||
}
|
||||
break;
|
||||
|
@ -427,6 +428,11 @@ var gInstallingPage = {
|
|||
};
|
||||
|
||||
var gErrorsPage = {
|
||||
onPageShow: function ()
|
||||
{
|
||||
document.documentElement.getButton("finish").focus();
|
||||
},
|
||||
|
||||
onShowErrors: function ()
|
||||
{
|
||||
openDialog("chrome://mozapps/content/update/errors.xul", "",
|
||||
|
@ -435,7 +441,6 @@ var gErrorsPage = {
|
|||
};
|
||||
|
||||
var gFinishedPage = {
|
||||
|
||||
onPageShow: function ()
|
||||
{
|
||||
gUpdateWizard.setButtonLabels(null, true, null, true, null, true);
|
||||
|
@ -464,6 +469,24 @@ var gFinishedPage = {
|
|||
}
|
||||
};
|
||||
|
||||
var gNoUpdatesPage = {
|
||||
onPageShow: function (aEvent)
|
||||
{
|
||||
gUpdateWizard.setButtonLabels(null, true, null, true, null, true);
|
||||
document.documentElement.getButton("finish").focus();
|
||||
if (gSourceEvent == nsIUpdateService.SOURCE_EVENT_MISMATCH) {
|
||||
document.getElementById("introUser").hidden = true;
|
||||
document.getElementById("introMismatch").hidden = false;
|
||||
document.getElementById("mismatchNoUpdates").hidden = false;
|
||||
|
||||
if (gUpdateWizard.shouldSuggestAutoChecking) {
|
||||
document.getElementById("mismatchIncompatibleRemaining").hidden = true;
|
||||
document.getElementById("mismatchIncompatibleRemaining2").hidden = false;
|
||||
document.getElementById("mismatchFinishedEnableChecking").hidden = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
|
|
@ -94,10 +94,28 @@
|
|||
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage id="noupdates" pageid="noupdates" next="finished"
|
||||
<wizardpage id="noupdates" pageid="noupdates"
|
||||
label="&noupdates.title;"
|
||||
onpageshow="gNoUpdatesPage.onPageShow();"
|
||||
onpageadvanced="gNoUpdatesPage.onPageAdvanced();">
|
||||
onpageshow="gNoUpdatesPage.onPageShow();">
|
||||
<label id="introUser">&noupdates.intro.user.label;</label>
|
||||
<label id="introMismatch" hidden="true">&noupdates.intro.mismatch.label;</label>
|
||||
<separator/>
|
||||
<vbox id="mismatchNoUpdates" hidden="true">
|
||||
<description id="mismatchIncompatibleRemaining" flex="1">
|
||||
&noupdates.intro2.mismatch.label;
|
||||
</description>
|
||||
<description id="mismatchIncompatibleRemaining2" flex="1" hidden="true">
|
||||
&noupdates.intro3.mismatch.label;
|
||||
</description>
|
||||
<separator class="thin"/>
|
||||
|
||||
<vbox align="left">
|
||||
<checkbox label="&noupdates.enableChecking.label;"
|
||||
id="mismatchFinishedEnableChecking" hidden="true"
|
||||
oncommand="gUpdateWizard.shouldAutoCheck = this.checked;"/>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage id="found" pageid="found" next="installing"
|
||||
|
|
|
@ -22,10 +22,6 @@
|
|||
|
||||
<!ENTITY noupdates.title "No Updates Found">
|
||||
<!ENTITY noupdates.intro.user.label "&brandShortName; was not able to find any available updates.">
|
||||
<!ENTITY noupdates.intro2.user.label "&brandShortName; will check periodically and inform you when
|
||||
updates become available.">
|
||||
<!ENTITY noupdates.intro3.user.label "&brandShortName; can check periodically and inform you when
|
||||
updates become available.">
|
||||
|
||||
<!ENTITY noupdates.intro.mismatch.label "&brandShortName; was not able to find any available updates -
|
||||
compatible versions may not be available at this time.">
|
||||
|
|
|
@ -49,6 +49,7 @@ interface nsIUpdateItem : nsISupports
|
|||
readonly attribute long row;
|
||||
readonly attribute wstring updateURL;
|
||||
readonly attribute wstring iconURL;
|
||||
readonly attribute wstring updateRDF;
|
||||
|
||||
const unsigned short TYPE_ANY = 0x01;
|
||||
const unsigned short TYPE_APP = 0x02;
|
||||
|
@ -62,7 +63,7 @@ interface nsIUpdateItem : nsISupports
|
|||
|
||||
void init(in string aID, in string aVersion, in wstring aName,
|
||||
in long aRow, in wstring aUpdateURL, in wstring aIconURL,
|
||||
in long aType);
|
||||
in wstring aUpdateRDF, in long aType);
|
||||
|
||||
readonly attribute wstring objectSource;
|
||||
};
|
||||
|
@ -94,3 +95,12 @@ interface nsIUpdateService : nsISupports
|
|||
readonly attribute wstring appUpdateURL;
|
||||
};
|
||||
|
||||
[scriptable, uuid(22d35700-5765-42e1-914b-a0da7c911a8c)]
|
||||
interface nsIVersionChecker : nsISupports
|
||||
{
|
||||
// -ve if B is newer
|
||||
// equal if A == B
|
||||
// +ve if A is newer
|
||||
long compare(in string aVersionA, in string aVersionB);
|
||||
};
|
||||
|
||||
|
|
|
@ -154,11 +154,7 @@ nsBackgroundUpdateService.prototype = {
|
|||
os.addObserver(this._updateObserver, "Update:Extension:Ended", false);
|
||||
os.addObserver(this._updateObserver, "Update:App:Ended", false);
|
||||
|
||||
var appUpdatesEnabled = this._pref.getBoolPref(PREF_UPDATE_APP_ENABLED);
|
||||
var extUpdatesEnabled = this._pref.getBoolPref(PREF_UPDATE_EXTENSIONS_ENABLED);
|
||||
|
||||
if (appUpdatesEnabled && ((aUpdateTypes == nsIUpdateItem.TYPE_ANY) ||
|
||||
(aUpdateTypes == nsIUpdateItem.TYPE_APP))) {
|
||||
if ((aUpdateTypes == nsIUpdateItem.TYPE_ANY) || (aUpdateTypes == nsIUpdateItem.TYPE_APP)) {
|
||||
var dsURI = this._pref.getComplexValue(PREF_UPDATE_APP_URI,
|
||||
Components.interfaces.nsIPrefLocalizedString).data;
|
||||
var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
|
||||
|
@ -172,7 +168,7 @@ nsBackgroundUpdateService.prototype = {
|
|||
sink.addXMLSinkObserver(new nsAppUpdateXMLRDFDSObserver(this));
|
||||
}
|
||||
}
|
||||
if (extUpdatesEnabled && (aUpdateTypes != nsIUpdateItem.TYPE_APP)) {
|
||||
if (aUpdateTypes != nsIUpdateItem.TYPE_APP) {
|
||||
var em = Components.classes["@mozilla.org/extensions/manager;1"]
|
||||
.getService(Components.interfaces.nsIExtensionManager);
|
||||
em.update(aItems, aItems.length);
|
||||
|
@ -215,8 +211,9 @@ nsBackgroundUpdateService.prototype = {
|
|||
|
||||
// do update checking here, parsing something like this format:
|
||||
var version = this._getProperty(aDataSource, appID, "version");
|
||||
var checker = new VersionChecker(appVersion, version);
|
||||
if (checker.isNewer) {
|
||||
var versionChecker = Components.classes["@mozilla.org/updates/version-checker;1"]
|
||||
.getService(Components.interfaces.nsIVersionChecker);
|
||||
if (versionChecker.compare(appVersion, version) < 0) {
|
||||
pref.setCharPref(PREF_UPDATE_APP_UPDATEVERSION, version);
|
||||
|
||||
var severity = this._getProperty(aDataSource, appID, "severity");
|
||||
|
@ -336,11 +333,9 @@ nsUpdateObserver.prototype = {
|
|||
this._updateTypes == nsIUpdateItem.TYPE_APP;
|
||||
var updatingExt = this._updateTypes != nsIUpdateItem.TYPE_APP;
|
||||
|
||||
if (this._pref.getBoolPref(PREF_UPDATE_APP_ENABLED) &&
|
||||
updatingApp)
|
||||
if (updatingApp)
|
||||
test |= UPDATED_APP;
|
||||
if (this._pref.getBoolPref(PREF_UPDATE_EXTENSIONS_ENABLED) &&
|
||||
updatingExt)
|
||||
if (updatingExt)
|
||||
test |= UPDATED_EXTENSIONS;
|
||||
|
||||
return (this._updateState & test) == test;
|
||||
|
@ -419,7 +414,7 @@ function UpdateItem ()
|
|||
}
|
||||
|
||||
UpdateItem.prototype = {
|
||||
init: function (aID, aVersion, aName, aRow, aUpdateURL, aIconURL, aType)
|
||||
init: function (aID, aVersion, aName, aRow, aUpdateURL, aIconURL, aUpdateRDF, aType)
|
||||
{
|
||||
this._id = aID;
|
||||
this._version = aVersion;
|
||||
|
@ -427,6 +422,7 @@ UpdateItem.prototype = {
|
|||
this._row = aRow;
|
||||
this._updateURL = aUpdateURL;
|
||||
this._iconURL = aIconURL;
|
||||
this._updateRDF = aUpdateRDF;
|
||||
this._type = aType;
|
||||
},
|
||||
|
||||
|
@ -436,6 +432,7 @@ UpdateItem.prototype = {
|
|||
get row() { return this._row; },
|
||||
get updateURL() { return this._updateURL; },
|
||||
get iconURL() { return this._iconURL },
|
||||
get updateRDF() { return this._updateRDF; },
|
||||
get type() { return this._type; },
|
||||
|
||||
get objectSource()
|
||||
|
@ -456,67 +453,66 @@ UpdateItem.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
// XXXben I would actually like to replace this with something more generic
|
||||
// like what samir has in nsUpdateNotifier.js
|
||||
function VersionChecker(aCurrentAppVer, aUpdateAppVer)
|
||||
function nsVersionChecker()
|
||||
{
|
||||
this._currAppVer = aCurrentAppVer;
|
||||
this._nextAppVer = aUpdateAppVer;
|
||||
}
|
||||
|
||||
VersionChecker.prototype = {
|
||||
currAppVersion: 0,
|
||||
nextAppversion: 0,
|
||||
|
||||
get isNewer ()
|
||||
nsVersionChecker.prototype = {
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsIVersionChecker
|
||||
|
||||
// -ve if B is newer
|
||||
// equal if A == B
|
||||
// +ve if A is newer
|
||||
compare: function (aVersionA, aVersionB)
|
||||
{
|
||||
var power = this._getLargestPower([this._currAppVer, this._nextAppVer]);
|
||||
this.currAppVersion = this._parseVersion(this._currAppVer, power);
|
||||
this.nextAppVersion = this._parseVersion(this._nextAppVer, power);
|
||||
return this.nextAppVersion > this.currAppVersion;
|
||||
var a = this._decomposeVersion(aVersionA);
|
||||
var b = this._decomposeVersion(aVersionB);
|
||||
return a - b;
|
||||
},
|
||||
|
||||
// Convert a version string into an integer value
|
||||
_parseVersion: function (aVersion, aPower)
|
||||
// Version strings get translated into a "score" that indicates how new
|
||||
// the product is.
|
||||
//
|
||||
// a.b.c+ -> a*1000 + b*100 + c*10 + 1*[+]
|
||||
// i.e 0.6.1+ = 6 * 100 + 1 * 10 = 611.
|
||||
_decomposeVersion: function (aVersion)
|
||||
{
|
||||
var parts = aVersion.split(".");
|
||||
var version = 0;
|
||||
if (aPower == 0)
|
||||
aPower = parts.length;
|
||||
var result = 0;
|
||||
if (aVersion.charAt(aVersion.length-1) == "+") {
|
||||
aVersion = aVersion.substr(0, aVersion.length-1);
|
||||
result += 1;
|
||||
}
|
||||
|
||||
for (var i = 0; i < parts.length; ++i) {
|
||||
var token = parts[i];
|
||||
if (token.charAt(token.length-1) == "+") {
|
||||
token = token.substr(0, token.lastIndexOf("+"));
|
||||
version += 1;
|
||||
if (token.length == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
version += parseInt(token) * Math.pow(10, aPower - i);
|
||||
}
|
||||
return version;
|
||||
var parts = aVersion.split(".");
|
||||
result += this._getValidInt(parts[0]) * 1000;
|
||||
result += this._getValidInt(parts[1]) * 100;
|
||||
result += this._getValidInt(parts[2]) * 10;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
_parsePower: function (aVersion)
|
||||
_getValidInt: function (aPartString)
|
||||
{
|
||||
return aVersion.split(".").length;
|
||||
var integer = parseInt(aPartString);
|
||||
if (isNaN(integer))
|
||||
return 0;
|
||||
return integer;
|
||||
},
|
||||
|
||||
_getLargestPower: function (aVersionArray)
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsISupports
|
||||
QueryInterface: function (aIID)
|
||||
{
|
||||
var biggestPower = 0;
|
||||
for (var i = 0; i < aVersionArray.length; ++i) {
|
||||
var power = this._parsePower(aVersionArray[i]);
|
||||
if (power > biggestPower)
|
||||
biggestPower = power;
|
||||
}
|
||||
return biggestPower;
|
||||
if (!aIID.equals(Components.interfaces.nsIVersionChecker) &&
|
||||
!aIID.equals(Components.interfaces.nsISupports))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var gUpdateService = null;
|
||||
var gUpdateService = null;
|
||||
var gVersionChecker = null;
|
||||
|
||||
var gModule = {
|
||||
_firstTime: true,
|
||||
|
@ -552,7 +548,7 @@ var gModule = {
|
|||
_objects: {
|
||||
manager: { CID: Components.ID("{B3C290A6-3943-4B89-8BBE-C01EB7B3B311}"),
|
||||
contractID: "@mozilla.org/updates/update-service;1",
|
||||
className: "Background Update Service",
|
||||
className: "Update Service",
|
||||
factory: {
|
||||
createInstance: function (aOuter, aIID)
|
||||
{
|
||||
|
@ -566,6 +562,22 @@ var gModule = {
|
|||
}
|
||||
}
|
||||
},
|
||||
version: { CID: Components.ID("{9408E0A5-509E-45E7-80C1-0F35B99FF7A9}"),
|
||||
contractID: "@mozilla.org/updates/version-checker;1",
|
||||
className: "Version Checker",
|
||||
factory: {
|
||||
createInstance: function (aOuter, aIID)
|
||||
{
|
||||
if (aOuter != null)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
if (!gVersionChecker)
|
||||
gVersionChecker = new nsVersionChecker();
|
||||
|
||||
return gVersionChecker.QueryInterface(aIID);
|
||||
}
|
||||
}
|
||||
},
|
||||
item: { CID: Components.ID("{F3294B1C-89F4-46F8-98A0-44E1EAE92518}"),
|
||||
contractID: "@mozilla.org/updates/item;1",
|
||||
className: "Extension Item",
|
||||
|
|
Загрузка…
Ссылка в новой задаче