📄 nsupdateservice.js
字号:
* See nsISupports.idl */ QueryInterface: function(iid) { if (!iid.equals(Components.interfaces.nsIApplicationUpdateService) && !iid.equals(Components.interfaces.nsITimerCallback) && !iid.equals(Components.interfaces.nsIObserver) && !iid.equals(Components.interfaces.nsISupports)) throw Components.results.NS_ERROR_NO_INTERFACE; return this; }};/** * A service to manage active and past updates. * @constructor */function UpdateManager() { // Ensure the Active Update file is loaded var updates = this._loadXMLFileIntoArray(getUpdateFile([FILE_UPDATE_ACTIVE])); if (updates.length > 0) this._activeUpdate = updates[0];}UpdateManager.prototype = { /** * All previously downloaded and installed updates, as an array of nsIUpdate * objects. */ _updates: null, /** * The current actively downloading/installing update, as a nsIUpdate object. */ _activeUpdate: null, /** * Loads an updates.xml formatted file into an array of nsIUpdate items. * @param file * A nsIFile for the updates.xml file * @returns The array of nsIUpdate items held in the file. */ _loadXMLFileIntoArray: function(file) { if (!file.exists()) { LOG("UpdateManager", "_loadXMLFileIntoArray: XML File does not exist"); return []; } var result = []; var fileStream = Components.classes["@mozilla.org/network/file-input-stream;1"] .createInstance(Components.interfaces.nsIFileInputStream); fileStream.init(file, MODE_RDONLY, PERMS_FILE, 0); try { var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"] .createInstance(Components.interfaces.nsIDOMParser); var doc = parser.parseFromStream(fileStream, "UTF-8", fileStream.available(), "text/xml"); var updateCount = doc.documentElement.childNodes.length; for (var i = 0; i < updateCount; ++i) { var updateElement = doc.documentElement.childNodes.item(i); if (updateElement.nodeType != Node.ELEMENT_NODE || updateElement.localName != "update") continue; updateElement.QueryInterface(Components.interfaces.nsIDOMElement); try { var update = new Update(updateElement); } catch (e) { LOG("UpdateManager", "_loadXMLFileIntoArray: invalid update"); continue; } result.push(new Update(updateElement)); } } catch (e) { LOG("UpdateManager", "_loadXMLFileIntoArray: Error constructing update list " + e); } fileStream.close(); return result; }, /** * Load the update manager, initializing state from state files. */ _ensureUpdates: function() { if (!this._updates) { this._updates = this._loadXMLFileIntoArray(getUpdateFile( [FILE_UPDATES_DB])); // Make sure that any active update is part of our updates list var active = this.activeUpdate; if (active) this._addUpdate(active); } }, /** * See nsIUpdateService.idl */ getUpdateAt: function(index) { this._ensureUpdates(); return this._updates[index]; }, /** * See nsIUpdateService.idl */ get updateCount() { this._ensureUpdates(); return this._updates.length; }, /** * See nsIUpdateService.idl */ get activeUpdate() { if (this._activeUpdate) { this._activeUpdate.QueryInterface(Components.interfaces.nsIUpdate_MOZILLA_1_8_BRANCH); if (this._activeUpdate.channel != getUpdateChannel()) { // User switched channels, clear out any old active updates and remove // partial downloads this._activeUpdate = null; // Destroy the updates directory, since we're done with it. cleanUpUpdatesDir(); } } return this._activeUpdate; }, set activeUpdate(activeUpdate) { this._addUpdate(activeUpdate); this._activeUpdate = activeUpdate; if (!activeUpdate) { // If |activeUpdate| is null, we have updated both lists - the active list // and the history list, so we want to write both files. this.saveUpdates(); } else this._writeUpdatesToXMLFile([this._activeUpdate], getUpdateFile([FILE_UPDATE_ACTIVE])); return activeUpdate; }, /** * Add an update to the Updates list. If the item already exists in the list, * replace the existing value with the new value. * @param update * The nsIUpdate object to add. */ _addUpdate: function(update) { if (!update) return; this._ensureUpdates(); if (this._updates) { for (var i = 0; i < this._updates.length; ++i) { if (this._updates[i] && this._updates[i].version == update.version && this._updates[i].buildID == update.buildID) { // Replace the existing entry with the new value, updating // all metadata. this._updates[i] = update; return; } } } // Otherwise add it to the front of the list. if (update) this._updates = [update].concat(this._updates); }, /** * Serializes an array of updates to an XML file * @param updates * An array of nsIUpdate objects * @param file * The nsIFile object to serialize to */ _writeUpdatesToXMLFile: function(updates, file) { var fos = Components.classes["@mozilla.org/network/safe-file-output-stream;1"] .createInstance(Components.interfaces.nsIFileOutputStream); var modeFlags = MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE; if (!file.exists()) file.create(nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE); fos.init(file, modeFlags, PERMS_FILE, 0); try { var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"] .createInstance(Components.interfaces.nsIDOMParser); const EMPTY_UPDATES_DOCUMENT = "<?xml version=\"1.0\"?><updates xmlns=\"http://www.mozilla.org/2005/app-update\"></updates>"; var doc = parser.parseFromString(EMPTY_UPDATES_DOCUMENT, "text/xml"); for (var i = 0; i < updates.length; ++i) { if (updates[i]) doc.documentElement.appendChild(updates[i].serialize(doc)); } var serializer = Components.classes["@mozilla.org/xmlextras/xmlserializer;1"] .createInstance(Components.interfaces.nsIDOMSerializer); serializer.serializeToStream(doc.documentElement, fos, null); } catch (e) { } closeSafeOutputStream(fos); }, /** * See nsIUpdateService.idl */ saveUpdates: function() { this._writeUpdatesToXMLFile([this._activeUpdate], getUpdateFile([FILE_UPDATE_ACTIVE])); if (this._updates) { this._writeUpdatesToXMLFile(this._updates, getUpdateFile([FILE_UPDATES_DB])); } }, /** * See nsISupports.idl */ QueryInterface: function(iid) { if (!iid.equals(Components.interfaces.nsIUpdateManager) && !iid.equals(Components.interfaces.nsISupports)) throw Components.results.NS_ERROR_NO_INTERFACE; return this; }};/** * Checker * Checks for new Updates * @constructor */function Checker() {}Checker.prototype = { /** * The XMLHttpRequest object that performs the connection. */ _request : null, /** * The nsIUpdateCheckListener callback */ _callback : null, /** * The URL of the update service XML file to connect to that contains details * about available updates. */ get updateURL() { var defaults = gPref.QueryInterface(Components.interfaces.nsIPrefService). getDefaultBranch(null); // Use the override URL if specified. var url = getPref("getCharPref", PREF_APP_UPDATE_URL_OVERRIDE, null); // Otherwise, construct the update URL from component parts. if (!url) { try { url = defaults.getCharPref(PREF_APP_UPDATE_URL); } catch (e) { } } if (!url || url == "") { LOG("Checker", "Update URL not defined"); return null; } url = url.replace(/%PRODUCT%/g, gApp.name); url = url.replace(/%VERSION%/g, gApp.version); url = url.replace(/%BUILD_ID%/g, gApp.appBuildID); url = url.replace(/%BUILD_TARGET%/g, gApp.OS + "_" + gABI); url = url.replace(/%OS_VERSION%/g, gOSVersion); url = url.replace(/%LOCALE%/g, getLocale()); url = url.replace(/%CHANNEL%/g, getUpdateChannel()); url = url.replace(/\+/g, "%2B"); LOG("Checker", "update url: " + url); return url; }, /** * See nsIUpdateService.idl */ checkForUpdates: function(listener, force) { if (!listener) throw Components.results.NS_ERROR_NULL_POINTER; if (!this.updateURL || (!this.enabled && !force)) return; this._request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]. createInstance(Components.interfaces.nsIXMLHttpRequest); this._request.open("GET", this.updateURL, true); this._request.channel.notificationCallbacks = new BadCertHandler(); this._request.overrideMimeType("text/xml"); this._request.setRequestHeader("Cache-Control", "no-cache"); var self = this; this._request.onerror = function(event) { self.onError(event); }; this._request.onload = function(event) { self.onLoad(event); }; this._request.onprogress = function(event) { self.onProgress(event); }; LOG("Checker", "checkForUpdates: sending request to " + this.updateURL); this._request.send(null); this._callback = listener; }, /** * When progress associated with the XMLHttpRequest is received. * @param event * The nsIDOMLSProgressEvent for the load. */ onProgress: function(event) { LOG("Checker", "onProgress: " + event.position + "/" + event.totalSize); this._callback.onProgress(event.target, event.position, event.totalSize); }, /** * Returns an array of nsIUpdate objects discovered by the update check. */ get _updates() { var updatesElement = this._request.responseXML.documentElement; if (!updatesElement) { LOG("Checker", "get_updates: empty updates document?!"); return []; } if (updatesElement.nodeName != "updates") { LOG("Checker", "get_updates: unexpected node name!"); throw ""; } var updates = []; for (var i = 0; i < updatesElement.childNodes.length; ++i) { var updateElement = updatesElement.childNodes.item(i); if (updateElement.nodeType != Node.ELEMENT_NODE || updateElement.localName != "update") continue; updateElement.QueryInterface(Components.interfaces.nsIDOMElement); try { var update = new Update(updateElement); } catch (e) { LOG("Checker", "Invalid <update/>, ignoring..."); continue; } update.serviceURL = this.updateURL; update.channel = getUpdateChannel(); updates.push(update); } return updates; }, /** * The XMLHttpRequest succeeded and the document was loaded. * @param event * The nsIDOMLSEvent for the load */ onLoad: function(event) { LOG("Checker", "onLoad: request completed downloading document"); try { checkCert(this._request.channel); // Analyze the resulting DOM and determine the set of updates to install var updates = this._updates; LOG("Checker", "Updates available: " + updates.length); // ... and tell the Update Service about what we discovered. this._callback.onCheckComplete(event.target, updates, updates.length); } catch (e) { LOG("Checker", "There was a problem with the update service URL specified, " + "either the XML file was malformed or it does not exist at the location " + "specified. Exception: " + e); var update = new Update(null); update.statusText = getStatusTextFromCode(404, 404); this._callback.onError(event.target, update); } this._request = null; }, /** * There was an error of some kind during the XMLHttpRequest * @param event * The nsIDOMLSEvent for the load */ onError: function(event) { LOG("Checker", "onError: error during load"); var request = event.target; try { var status = request.status; } catch (e) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -