📄 nsupdatenotifier.js
字号:
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is the Update Notifier. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 2002 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Samir Gehani <sgehani@netscape.com> (Original Author) * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */const kDebug = false;const kUpdateCheckDelay = 5 * 60 * 1000; // 5 minutesconst kUNEnabledPref = "update_notifications.enabled";const kUNDatasourceURIPref = "update_notifications.provider.0.datasource";const kUNFrequencyPref = "update_notifications.provider.0.frequency";const kUNLastCheckedPref = "update_notifications.provider.0.last_checked";const kUNBundleURI = "chrome://communicator/locale/update-notifications.properties";//////////////////////////////////////////////////////////////////////////// nsUpdateNotifier : nsIProfileStartupListener, nsIObserver//// Checks for updates of the client by polling a distributor's website// for the latest available version of the software and comparing it// with the version of the running client.//////////////////////////////////////////////////////////////////////////var nsUpdateNotifier ={ mInitialized: false, onProfileStartup: function(aProfileName) { debug("onProfileStartup"); // Check if we've already been called. if (this.mInitialized) return; this.mInitialized = true; // now wait for the first app window to open var observerService = Components. classes["@mozilla.org/observer-service;1"]. getService(Components.interfaces.nsIObserverService); observerService.addObserver(this, "domwindowopened", false); }, mTimer: null, // need to hold on to timer ref observe: function(aSubject, aTopic, aData) { debug("observe: " + aTopic); if (aTopic == "domwindowopened") { try { const kITimer = Components.interfaces.nsITimer; this.mTimer = Components.classes["@mozilla.org/timer;1"]. createInstance(kITimer); this.mTimer.init(this, kUpdateCheckDelay, kITimer.TYPE_ONE_SHOT); // we are no longer interested in the ``domwindowopened'' topic var observerService = Components. classes["@mozilla.org/observer-service;1"]. getService(Components.interfaces.nsIObserverService); observerService.removeObserver(this, "domwindowopened"); // but we are interested in removing our timer reference on XPCOM // shutdown so as not to leak. observerService.addObserver(this, "xpcom-shutdown", false); } catch (ex) { debug("Exception init'ing timer: " + ex); } } else if (aTopic == "timer-callback") { this.mTimer = null; // free up timer so it can be gc'ed this.checkForUpdate(); } else if (aTopic == "xpcom-shutdown") { /* * We need to drop our timer reference here to avoid a leak * since the timer keeps a reference to the observer. */ this.mTimer = null; } }, checkForUpdate: function() { debug("checkForUpdate"); if (this.shouldCheckForUpdate()) { try { // get update ds URI from prefs var prefs = Components.classes["@mozilla.org/preferences-service;1"]. getService(Components.interfaces.nsIPrefBranch); var updateDatasourceURI = prefs. getComplexValue(kUNDatasourceURIPref, Components.interfaces.nsIPrefLocalizedString).data; var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]. getService(Components.interfaces.nsIRDFService); var ds = rdf.GetDataSource(updateDatasourceURI); ds = ds.QueryInterface(Components.interfaces.nsIRDFXMLSink); ds.addXMLSinkObserver(nsUpdateDatasourceObserver); } catch (ex) { debug("Exception getting updates.rdf: " + ex); } } }, shouldCheckForUpdate: function() { debug("shouldCheckForUpdate"); var shouldCheck = false; try { var prefs = Components.classes["@mozilla.org/preferences-service;1"]. getService(Components.interfaces.nsIPrefBranch); if (prefs.getBoolPref(kUNEnabledPref)) { var freq = prefs.getIntPref(kUNFrequencyPref) * (24 * 60 * 60); // secs var now = (new Date().valueOf())/1000; // secs if (!prefs.prefHasUserValue(kUNLastCheckedPref)) { // setting last_checked pref first time so must randomize in // order that servers don't get flooded with updates.rdf checks // (and eventually downloads of new clients) all at the same time var randomizedLastChecked = now + freq * (1 + Math.random()); prefs.setIntPref(kUNLastCheckedPref, randomizedLastChecked); return false; } var lastChecked = prefs.getIntPref(kUNLastCheckedPref); if ((lastChecked + freq) > now) return false; prefs.setIntPref(kUNLastCheckedPref, now); prefs = prefs.QueryInterface(Components.interfaces.nsIPrefService); prefs.savePrefFile(null); // flush prefs now shouldCheck = true; } } catch (ex) { shouldCheck = false; debug("Exception in shouldCheckForUpdate: " + ex); } return shouldCheck; }, QueryInterface: function(aIID) { if (aIID.equals(Components.interfaces.nsIObserver) || aIID.equals(Components.interfaces.nsIProfileStartupListener) || aIID.equals(Components.interfaces.nsISupports)) return this; Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE; return null; }}//////////////////////////////////////////////////////////////////////////// nsUpdateDatasourceObserver : nsIRDFXMLSinkObserver//// Gets relevant info on latest available update after the updates.rdf// datasource has completed loading asynchronously.//////////////////////////////////////////////////////////////////////////var nsUpdateDatasourceObserver ={ onBeginLoad: function(aSink) { }, onInterrupt: function(aSink) { }, onResume: function(aSink) { }, onEndLoad: function(aSink) { debug("onEndLoad"); aSink.removeXMLSinkObserver(this); var ds = aSink.QueryInterface(Components.interfaces.nsIRDFDataSource); var updateInfo = this.getUpdateInfo(ds); if (updateInfo && this.newerVersionAvailable(updateInfo)) { var promptService = Components. classes["@mozilla.org/embedcomp/prompt-service;1"]. getService(Components.interfaces.nsIPromptService); var winWatcher = Components. classes["@mozilla.org/embedcomp/window-watcher;1"]. getService(Components.interfaces.nsIWindowWatcher); var unBundle = this.getBundle(kUNBundleURI); if (!unBundle) return; var title = unBundle.formatStringFromName("title", [updateInfo.productName], 1); var desc = unBundle.formatStringFromName("desc", [updateInfo.productName], 1); var button0Text = unBundle.GetStringFromName("getItNow"); var button1Text = unBundle.GetStringFromName("noThanks"); var checkMsg = unBundle.GetStringFromName("dontAskAgain"); var checkVal = {value:0}; var result = promptService.confirmEx(winWatcher.activeWindow, title, desc, (promptService.BUTTON_POS_0 * promptService.BUTTON_TITLE_IS_STRING) + (promptService.BUTTON_POS_1 * promptService.BUTTON_TITLE_IS_STRING), button0Text, button1Text, null, checkMsg, checkVal); // user wants update now so open new window // (result => 0 is button0) if (result == 0) { var browserURL = "chrome://navigator/content/navigator.xul"; try { browserURL = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch) .getCharPref("browser.chromeURL"); } catch (e) { } var argstring = Components.classes["@mozilla.org/supports-string;1"] .createInstance(Components.interfaces.nsISupportsString); argstring.data = updateInfo.URL; winWatcher.openWindow(winWatcher.activeWindow, browserURL, "_blank", "chrome,all,dialog=no", argstring); } // if "Don't ask again" was checked disable update notifications if (checkVal.value) { var prefs = Components.classes["@mozilla.org/preferences-service;1"]. getService(Components.interfaces.nsIPrefBranch); prefs.setBoolPref(kUNEnabledPref, false); } } }, onError: function(aSink, aStatus, aErrorMsg) { debug("Error " + aStatus + ": " + aErrorMsg); aSink.removeXMLSinkObserver(this); }, getUpdateInfo: function(aDS) { var info = null; try { var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]. getService(Components.interfaces.nsIRDFService); var src = "urn:updates:latest"; info = new Object; info.registryName = this.getTarget(rdf, aDS, src, "registryName"); info.version = this.getTarget(rdf, aDS, src, "version");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -