Bug 471219 - Store timer registrations somewhere permanent. r=dtownsend

This commit is contained in:
Robert Strong 2009-09-18 11:03:27 -07:00
Родитель 064c0629d7
Коммит 86d9b35a99
13 изменённых файлов: 421 добавлений и 299 удалений

Просмотреть файл

@ -89,8 +89,16 @@ pref("extensions.blocklist.detailsURL", "https://www.mozilla.com/%LOCALE%/blockl
// Dictionary download preference
pref("browser.dictionaries.download.url", "https://%LOCALE%.add-ons.mozilla.com/%LOCALE%/firefox/%VERSION%/dictionaries/");
// Update Timer Manager preferences
// Interval: When all registered timers should be checked (in milliseconds)
// default=10 minutes
pref("app.update.timer", 600000);
// App-specific update preferences
// The interval to check for updates (app.update.interval) is defined in
// firefox-branding.js
// Whether or not app updates are enabled
pref("app.update.enabled", true);
@ -127,9 +135,6 @@ pref("app.update.url", "https://aus2.mozilla.org/update/3/%PRODUCT%/%VERSION%/%B
// latest download (in seconds) default=1 day
pref("app.update.nagTimer.restart", 86400);
// Interval: When all registered timers should be checked (in milliseconds)
// default=10 minutes
pref("app.update.timer", 600000);
// Give the user x seconds to react before showing the big UI. default=12 hours
pref("app.update.promptWaitTime", 43200);
// Show the Update Checking/Ready UI when the user was idle for x seconds
@ -153,7 +158,6 @@ pref("app.update.incompatible.mode", 0);
// e.g.
// extensions.{GUID}.update.enabled
// extensions.{GUID}.update.url
// extensions.{GUID}.update.interval
// .. etc ..
//
pref("extensions.update.enabled", true);

Просмотреть файл

@ -154,7 +154,13 @@ MicrosummaryService.prototype = {
classDescription: "Microsummary Service",
contractID: "@mozilla.org/microsummary/service;1",
classID: Components.ID("{460a9792-b154-4f26-a922-0f653e2c8f91}"),
_xpcom_categories: [{ category: "update-timer",
value: "@mozilla.org/microsummary/service;1," +
"getService,microsummary-generator-update-timer," +
"browser.microsummary.generatorUpdateInterval," +
GENERATOR_INTERVAL }],
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMicrosummaryService,
Ci.nsITimerCallback,
Ci.nsISupportsWeakReference,
Ci.nsIAnnotationObserver,
Ci.nsIObserver]),
@ -172,6 +178,11 @@ MicrosummaryService.prototype = {
}
},
// cross-session timer used to periodically check for generator updates.
notify: function MSS_notify(timer) {
this._updateGenerators();
},
_initTimers: function MSS__initTimers() {
if (this._timer)
this._timer.cancel();
@ -188,18 +199,6 @@ MicrosummaryService.prototype = {
this._timer.initWithCallback(callback,
CHECK_INTERVAL,
this._timer.TYPE_REPEATING_SLACK);
// Setup a cross-session timer to periodically check for generator updates.
var updateManager = Cc["@mozilla.org/updates/timer-manager;1"].
getService(Ci.nsIUpdateTimerManager);
var interval = getPref("browser.microsummary.generatorUpdateInterval",
GENERATOR_INTERVAL);
var updateCallback = {
_svc: this,
notify: function(timer) { this._svc._updateGenerators() }
};
updateManager.registerTimer("microsummary-generator-update-timer",
updateCallback, interval);
},
_destroy: function MSS__destroy() {

Просмотреть файл

@ -113,9 +113,6 @@ registrar.registerFactory(Components.ID("{fbfae60b-64a4-44ef-a911-08ceb70b9f31}"
"XULAppInfo", "@mozilla.org/xre/app-info;1",
XULAppInfoFactory);
var updateSvc = Cc["@mozilla.org/updates/update-service;1"].
getService(Ci.nsISupports);
var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
function uri(spec) {

Просмотреть файл

@ -388,10 +388,6 @@ Blocklist.prototype = {
gBlocklistLevel = Math.min(getPref("getIntPref", PREF_BLOCKLIST_LEVEL, DEFAULT_LEVEL),
MAX_BLOCK_LEVEL);
gPref.addObserver("extensions.blocklist.", this, false);
var tm = Cc["@mozilla.org/updates/timer-manager;1"].
getService(Ci.nsIUpdateTimerManager);
var interval = getPref("getIntPref", PREF_BLOCKLIST_INTERVAL, 86400);
tm.registerTimer("blocklist-background-update-timer", this, interval);
break;
case "xpcom-shutdown":
gOS.removeObserver(this, "xpcom-shutdown");
@ -928,7 +924,11 @@ Blocklist.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsIBlocklistService,
Ci.nsITimerCallback]),
_xpcom_categories: [{ category: "profile-after-change" }]
_xpcom_categories: [{ category: "profile-after-change" },
{ category: "update-timer",
value: "@mozilla.org/extensions/blocklist;1," +
"getService,blocklist-background-update-timer," +
PREF_BLOCKLIST_INTERVAL + ",86400" }]
};
/**

Просмотреть файл

@ -2618,23 +2618,9 @@ ExtensionManager.prototype = {
ERROR("Error flushing caches: " + e);
}
if (!needsRestart)
this._startTimers();
return needsRestart;
},
/**
* Begins all background update check timers
*/
_startTimers: function EM__startTimers() {
// Register a background update check timer
var tm = Cc["@mozilla.org/updates/timer-manager;1"].
getService(Ci.nsIUpdateTimerManager);
var interval = getPref("getIntPref", PREF_EM_UPDATE_INTERVAL, 86400);
tm.registerTimer("addon-background-update-timer", this, interval);
},
/**
* Notified when a timer fires
* @param timer
@ -5468,7 +5454,11 @@ ExtensionManager.prototype = {
classDescription: "Extension Manager",
contractID: "@mozilla.org/extensions/manager;1",
classID: Components.ID("{8A115FAA-7DCB-4e8f-979B-5F53472F51CF}"),
_xpcom_categories: [{ category: "profile-after-change" }],
_xpcom_categories: [{ category: "profile-after-change" },
{ category: "update-timer",
value: "@mozilla.org/extensions/manager;1," +
"getService,addon-background-update-timer," +
PREF_EM_UPDATE_INTERVAL + ",86400" }],
_xpcom_factory: {
createInstance: function(outer, iid) {
if (outer != null)

Просмотреть файл

@ -197,10 +197,6 @@ function createAppInfo(id, name, version, platformVersion)
*/
function startupEM()
{
// Make sure the update service is initialised.
var updateSvc = Components.classes["@mozilla.org/updates/update-service;1"]
.getService(Components.interfaces.nsISupports);
gEM = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager);

Просмотреть файл

@ -43,6 +43,7 @@ const PREF_APP_DISTRIBUTION = "distribution.id";
const PREF_APP_DISTRIBUTION_VERSION = "distribution.version";
const PREF_APP_UPDATE_CHANNEL = "app.update.channel";
const PREF_GENERAL_USERAGENT_LOCALE = "general.useragent.locale";
const CATEGORY_UPDATE_TIMER = "update-timer";
// Get the HTTP server.
do_load_httpd_js();
@ -53,18 +54,23 @@ var gBlocklist;
// This is a replacement for the timer service so we can trigger timers
var timerService = {
timers: {},
registerTimer: function(id, callback, interval) {
this.timers[id] = callback;
},
hasTimer: function(id) {
return id in this.timers;
var catMan = Components.classes["@mozilla.org/categorymanager;1"]
.getService(Components.interfaces.nsICategoryManager);
var entries = catMan.enumerateCategory(CATEGORY_UPDATE_TIMER);
while (entries.hasMoreElements()) {
var entry = entries.getNext().QueryInterface(Components.interfaces.nsISupportsCString).data;
var value = catMan.getCategoryEntry(CATEGORY_UPDATE_TIMER, entry);
var timerID = value.split(",")[3];
if (id == timerID) {
return true;
}
}
return false;
},
fireTimer: function(id) {
this.timers[id].notify(null);
gBlocklist.QueryInterface(Components.interfaces.nsITimerCallback).notify(null);
},
QueryInterface: function(iid) {

Просмотреть файл

@ -44,7 +44,11 @@ include $(DEPTH)/config/autoconf.mk
MODULE = update
XPIDL_MODULE = update
XPIDLSRCS = nsIUpdateService.idl
XPIDLSRCS = nsIUpdateTimerManager.idl
ifdef MOZ_UPDATER
XPIDLSRCS += nsIUpdateService.idl
endif
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -43,7 +43,6 @@ interface nsIDOMWindow;
interface nsIRequest;
interface nsIRequestObserver;
interface nsISimpleEnumerator;
interface nsITimerCallback;
interface nsIXMLHttpRequest;
/**
@ -487,29 +486,3 @@ interface nsIUpdatePrompt : nsISupports
*/
void showUpdateHistory(in nsIDOMWindow parent);
};
/**
* An interface describing a global application service that allows long
* duration (e.g. 1-7 or more days, weeks or months) timers to be registered
* and then fired.
*/
[scriptable, uuid(0765c92c-6145-4253-9db4-594d8023087e)]
interface nsIUpdateTimerManager : nsISupports
{
/**
* Register an interval with the timer manager. The timer manager
* periodically checks to see if the interval has expired and if it has
* calls the specified callback. This is persistent across application
* restarts and can handle intervals of long durations.
* @param id
* An id that identifies the interval, used for persistence
* @param callback
* A nsITimerCallback object that is notified when the interval
* expires
* @param interval
* The length of time, in seconds, of the interval
*/
void registerTimer(in AString id,
in nsITimerCallback callback,
in unsigned long interval);
};

Просмотреть файл

@ -0,0 +1,87 @@
/* -*- Mode: IDL; 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 Timer Manager
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@mozilla.org>
* Robert Strong <robert.bugzilla@gmail.com>
*
* 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 ***** */
#include "nsISupports.idl"
interface nsITimerCallback;
/**
* An interface describing a global application service that allows long
* duration (e.g. 1-7 or more days, weeks or months) timers to be registered
* and then fired.
*/
[scriptable, uuid(0765c92c-6145-4253-9db4-594d8023087e)]
interface nsIUpdateTimerManager : nsISupports
{
/**
* Register an interval with the timer manager. The timer manager
* periodically checks to see if the interval has expired and if it has
* calls the specified callback. This is persistent across application
* restarts and can handle intervals of long durations.
* @param id
* An id that identifies the interval, used for persistence
* @param callback
* A nsITimerCallback object that is notified when the interval
* expires
* @param interval
* The length of time, in seconds, of the interval
*
* Note: to avoid having to instantiate a component to call registerTimer
* the component can intead register an update-timer category with comma
* separated values as a single string representing the timer as follows.
*
* _xpcom_categories: [{ category: "update-timer",
* value: "contractID," +
* "method," +
* "id," +
* "preference," +
* "interval" }],
* the values are as follows
* contractID : the contract ID for the component.
* method : the method used to instantiate the interface. This should be
* either getService or createInstance depending on your
* component.
* id : the id that identifies the interval, used for persistence.
* preference : the preference to for timer interval. This value can be
* optional by specifying an empty string for the value.
* interval : the default interval in seconds for the timer.
*/
void registerTimer(in AString id,
in nsITimerCallback callback,
in unsigned long interval);
};

Просмотреть файл

@ -45,6 +45,7 @@ include $(DEPTH)/config/autoconf.mk
MODULE = update
ifdef MOZ_UPDATER
DEFINES += -DMOZ_UPDATER
DIRS = updater
endif

Просмотреть файл

@ -49,12 +49,16 @@ const Cr = Components.results;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
const PREF_APP_UPDATE_LASTUPDATETIME_FMT = "app.update.lastUpdateTime.%ID%";
const PREF_APP_UPDATE_TIMER = "app.update.timer";
const CATEGORY_UPDATE_TIMER = "update-timer";
#ifdef MOZ_UPDATER
const PREF_APP_UPDATE_ENABLED = "app.update.enabled";
const PREF_APP_UPDATE_AUTO = "app.update.auto";
const PREF_APP_UPDATE_MODE = "app.update.mode";
const PREF_APP_UPDATE_SILENT = "app.update.silent";
const PREF_APP_UPDATE_INTERVAL = "app.update.interval";
const PREF_APP_UPDATE_TIMER = "app.update.timer";
const PREF_APP_UPDATE_IDLETIME = "app.update.idletime";
const PREF_APP_UPDATE_PROMPTWAITTIME = "app.update.promptWaitTime";
const PREF_APP_UPDATE_LOG_BRANCH = "app.update.log.";
@ -64,7 +68,6 @@ const PREF_APP_UPDATE_URL_DETAILS = "app.update.url.details";
const PREF_APP_UPDATE_CHANNEL = "app.update.channel";
const PREF_APP_UPDATE_BACKGROUND_INTERVAL = "app.update.download.backgroundInterval";
const PREF_APP_UPDATE_SHOW_INSTALLED_UI = "app.update.showInstalledUI";
const PREF_APP_UPDATE_LASTUPDATETIME_FMT = "app.update.lastUpdateTime.%ID%";
const PREF_APP_UPDATE_INCOMPATIBLE_MODE = "app.update.incompatible.mode";
const PREF_UPDATE_NEVER_BRANCH = "app.update.never.";
const PREF_PARTNER_BRANCH = "app.partner.";
@ -124,18 +127,59 @@ const DOWNLOAD_FOREGROUND_INTERVAL = 0;
const UPDATE_WINDOW_NAME = "Update:Wizard";
var gApp = null;
var gPref = null;
var gABI = null;
var gOSVersion = null;
var gLocale = null;
var gConsole = null;
var gCanUpdate = null;
var gLogEnabled = { };
// shared code for suppressing bad cert dialogs
#include ../../shared/src/badCertHandler.js
#endif /* MOZ_UPDATER */
XPCOMUtils.defineLazyServiceGetter(this, "gPref",
"@mozilla.org/preferences-service;1",
"nsIPrefBranch2");
/**
* Gets a preference value, handling the case where there is no default.
* @param func
* The name of the preference function to call, on nsIPrefBranch
* @param preference
* The name of the preference
* @param defaultValue
* The default value to return in the event the preference has
* no setting
* @returns The value of the preference, or undefined if there was no
* user or default value.
*/
function getPref(func, preference, defaultValue) {
try {
return gPref[func](preference);
}
catch (e) {
}
return defaultValue;
}
XPCOMUtils.defineLazyGetter(this, "gLogEnabled", function() {
let logEnabled = { };
try {
let ps = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService);
let logBranch = ps.getBranch(PREF_APP_UPDATE_LOG_BRANCH);
let modules = logBranch.getChildList("", { value: 0 });
for (let i = 0; i < modules.length; ++i) {
if (logBranch.prefHasUserValue(modules[i]))
logEnabled[modules[i]] = logBranch.getBoolPref(modules[i]);
}
}
catch (e) {
}
return logEnabled;
});
XPCOMUtils.defineLazyServiceGetter(this, "gConsole",
"@mozilla.org/consoleservice;1",
"nsIConsoleService");
/**
* Logs a string to the error console.
* @param string
@ -144,12 +188,60 @@ var gLogEnabled = { };
function LOG(module, string) {
if (module in gLogEnabled || "all" in gLogEnabled) {
dump("*** AUS:SVC " + module + ":" + string + "\n");
// On startup gConsole may not be initialized
if (gConsole)
gConsole.logStringMessage("AUS:SVC " + module + ":" + string);
gConsole.logStringMessage("AUS:SVC " + module + ":" + string);
}
}
#ifdef MOZ_UPDATER
XPCOMUtils.defineLazyGetter(this, "gApp", function() {
return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).
QueryInterface(Ci.nsIXULRuntime);
});
XPCOMUtils.defineLazyGetter(this, "gABI", function() {
let abi = null;
try {
abi = gApp.XPCOMABI;
}
catch (e) {
LOG("General", "gABI - XPCOM ABI unknown: updates are not possible.");
}
#ifdef XP_MACOSX
// Mac universal build should report a different ABI than either macppc
// or mactel.
let macutils = Cc["@mozilla.org/xpcom/mac-utils;1"].
getService(Ci.nsIMacUtils);
if (macutils.isUniversalBinary)
abi = "Universal-gcc3";
#endif
return abi;
});
XPCOMUtils.defineLazyGetter(this, "gOSVersion", function() {
let osVersion;
let sysInfo = Cc["@mozilla.org/system-info;1"].
getService(Ci.nsIPropertyBag2);
try {
osVersion = sysInfo.getProperty("name") + " " + sysInfo.getProperty("version");
}
catch (e) {
LOG("UpdateService", "init - OS Version unknown: updates are not possible.");
}
if (osVersion) {
try {
osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")";
}
catch (e) {
// Not all platforms have a secondary widget library, so an error is nothing to worry about.
}
osVersion = encodeURIComponent(osVersion);
}
return osVersion;
});
/**
* Convert a string containing binary values to hex.
*/
@ -504,27 +596,6 @@ function cleanupActiveUpdate(key) {
cleanUpUpdatesDir(key);
}
/**
* Gets a preference value, handling the case where there is no default.
* @param func
* The name of the preference function to call, on nsIPrefBranch
* @param preference
* The name of the preference
* @param defaultValue
* The default value to return in the event the preference has
* no setting
* @returns The value of the preference, or undefined if there was no
* user or default value.
*/
function getPref(func, preference, defaultValue) {
try {
return gPref[func](preference);
}
catch (e) {
}
return defaultValue;
}
/**
* Gets the locale from the update.locale file for replacing %LOCALE% in the
* update url. The update.locale file can be located in the application
@ -1042,56 +1113,11 @@ const UpdateServiceFactory = {
* @constructor
*/
function UpdateService() {
gApp = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).
QueryInterface(Ci.nsIXULRuntime);
gPref = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch2);
gConsole = Cc["@mozilla.org/consoleservice;1"].
getService(Ci.nsIConsoleService);
// Not all builds have a known ABI
try {
gABI = gApp.XPCOMABI;
}
catch (e) {
LOG("UpdateService", "init - XPCOM ABI unknown: updates are not possible.");
}
var osVersion;
var sysInfo = Cc["@mozilla.org/system-info;1"].
getService(Ci.nsIPropertyBag2);
try {
osVersion = sysInfo.getProperty("name") + " " + sysInfo.getProperty("version");
}
catch (e) {
LOG("UpdateService", "init - OS Version unknown: updates are not possible.");
}
if (osVersion) {
try {
osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")";
}
catch (e) {
// Not all platforms have a secondary widget library, so an error is nothing to worry about.
}
gOSVersion = encodeURIComponent(osVersion);
}
#ifdef XP_MACOSX
// Mac universal build should report a different ABI than either macppc
// or mactel.
var macutils = Cc["@mozilla.org/xpcom/mac-utils;1"].
getService(Ci.nsIMacUtils);
if (macutils.isUniversalBinary)
gABI = "Universal-gcc3";
#endif
// Start the update timer only after a profile has been selected so that the
// appropriate values for the update check are read from the user's profile.
var os = getObserverService();
os.addObserver(this, "profile-after-change", false);
os.addObserver(this, "final-ui-startup", false);
// Observe xpcom-shutdown to unhook pref branch observers above to avoid
// shutdown leaks.
@ -1123,11 +1149,6 @@ UpdateService.prototype = {
var os = getObserverService();
switch (topic) {
case "profile-after-change":
os.removeObserver(this, "profile-after-change");
os.addObserver(this, "final-ui-startup", false);
this._start();
break;
case "final-ui-startup":
os.removeObserver(this, "final-ui-startup");
this._final_ui_start();
@ -1137,29 +1158,10 @@ UpdateService.prototype = {
// Prevent leaking the downloader (bug 454964)
this._downloader = null;
// Release Services
gApp = null;
gPref = null;
gConsole = null;
break;
}
},
/**
* Start the Update Service
*/
_start: function AUS__start() {
// Start logging
this._initLoggingPrefs();
// Register a background update check timer
var tm = Cc["@mozilla.org/updates/timer-manager;1"].
getService(Ci.nsIUpdateTimerManager);
var interval = getPref("getIntPref", PREF_APP_UPDATE_INTERVAL, 86400);
tm.registerTimer("background-update-timer", this, interval);
},
/**
* The following needs to be performed after final-ui-startup (bug 497578)
* 1. post update processing
@ -1307,26 +1309,6 @@ UpdateService.prototype = {
}
},
/**
* Initialize Logging preferences, formatted like so:
* app.update.log.<moduleName> = <true|false>
*/
_initLoggingPrefs: function AUS__initLoggingPrefs() {
try {
var ps = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService);
var logBranch = ps.getBranch(PREF_APP_UPDATE_LOG_BRANCH);
var modules = logBranch.getChildList("", { value: 0 });
for (var i = 0; i < modules.length; ++i) {
if (logBranch.prefHasUserValue(modules[i]))
gLogEnabled[modules[i]] = logBranch.getBoolPref(modules[i]);
}
}
catch (e) {
}
},
/**
* Notified when a timer fires
* @param timer
@ -1867,7 +1849,11 @@ UpdateService.prototype = {
classDescription: "Update Service",
contractID: "@mozilla.org/updates/update-service;1",
classID: Components.ID("{B3C290A6-3943-4B89-8BBE-C01EB7B3B311}"),
_xpcom_categories: [{ category: "app-startup", service: true }],
_xpcom_categories: [{ category: "app-startup", service: true },
{ category: CATEGORY_UPDATE_TIMER,
value: "@mozilla.org/updates/update-service;1," +
"getService,background-update-timer," +
PREF_APP_UPDATE_INTERVAL + ",86400" }],
_xpcom_factory: UpdateServiceFactory,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIApplicationUpdateService,
Ci.nsIAddonUpdateCheckListener,
@ -2867,100 +2853,6 @@ Downloader.prototype = {
Ci.nsIInterfaceRequestor])
};
/**
* A manager for update check timers. Manages timers that fire over long
* periods of time (e.g. days, weeks).
* @constructor
*/
function TimerManager() {
getObserverService().addObserver(this, "xpcom-shutdown", false);
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
var timerInterval = getPref("getIntPref", PREF_APP_UPDATE_TIMER, 600000);
this._timer.initWithCallback(this, timerInterval,
Ci.nsITimer.TYPE_REPEATING_SLACK);
}
TimerManager.prototype = {
/**
* See nsIObserver.idl
*/
observe: function TM_observe(subject, topic, data) {
if (topic == "xpcom-shutdown") {
getObserverService().removeObserver(this, "xpcom-shutdown");
// Release everything we hold onto.
for (var timerID in this._timers)
delete this._timers[timerID];
this._timer = null;
this._timers = null;
}
},
/**
* The Checker Timer
*/
_timer: null,
/**
* The set of registered timers.
*/
_timers: { },
/**
* Called when the checking timer fires.
* @param timer
* The checking timer that fired.
*/
notify: function TM_notify(timer) {
for (var timerID in this._timers) {
var timerData = this._timers[timerID];
var lastUpdateTime = timerData.lastUpdateTime;
var now = Math.round(Date.now() / 1000);
// Fudge the lastUpdateTime by some random increment of the update
// check interval (e.g. some random slice of 10 minutes) so that when
// the time comes to check, we offset each client request by a random
// amount so they don't all hit at once. app.update.timer is in milliseconds,
// whereas app.update.lastUpdateTime is in seconds
var timerInterval = getPref("getIntPref", PREF_APP_UPDATE_TIMER, 600000);
lastUpdateTime += Math.round(Math.random() * timerInterval / 1000);
if ((now - lastUpdateTime) > timerData.interval &&
timerData.callback instanceof Ci.nsITimerCallback) {
timerData.callback.notify(timer);
timerData.lastUpdateTime = now;
var preference = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, timerID);
gPref.setIntPref(preference, now);
}
}
},
/**
* See nsIUpdateService.idl
*/
registerTimer: function TM_registerTimer(id, callback, interval) {
var preference = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, id);
var now = Math.round(Date.now() / 1000);
var lastUpdateTime = null;
if (gPref.prefHasUserValue(preference)) {
lastUpdateTime = gPref.getIntPref(preference);
} else {
gPref.setIntPref(preference, now);
lastUpdateTime = now;
}
this._timers[id] = { callback : callback,
interval : interval,
lastUpdateTime : lastUpdateTime };
},
classDescription: "Timer Manager",
contractID: "@mozilla.org/updates/timer-manager;1",
classID: Components.ID("{B322A5C0-A419-484E-96BA-D7182163899F}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdateTimerManager,
Ci.nsITimerCallback,
Ci.nsIObserver])
};
/**
* UpdatePrompt
* An object which can prompt the user with information about updates, request
@ -3025,7 +2917,7 @@ UpdatePrompt.prototype = {
*/
showUpdateInstalled: function UP_showUpdateInstalled() {
if (!this._enabled || this._getUpdateWindow() ||
!getPref("getBoolPref", PREF_APP_UPDATE_SHOW_INSTALLED_UI, true))
!getPref("getBoolPref", PREF_APP_UPDATE_SHOW_INSTALLED_UI, false))
return;
var page = "installed";
@ -3260,9 +3152,183 @@ UpdatePrompt.prototype = {
classID: Components.ID("{27ABA825-35B5-4018-9FDD-F99250A0E722}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdatePrompt])
};
#endif /* MOZ_UPDATER */
/**
* A manager for timers. Manages timers that fire over long periods of time
* (e.g. days, weeks, months).
* @constructor
*/
function TimerManager() {
}
TimerManager.prototype = {
/**
* The Checker Timer
*/
_timer: null,
/**
* The Checker Timer interval as specified by the app.update.timer pref. If
* the app.update.timer pref doesn't exist this will default to 600000.
*/
_timerInterval: null,
/**
* The set of registered timers.
*/
_timers: { },
/**
* The amount to fudge the lastUpdateTime where fudge is a random increment of
* the update check interval (e.g. some random slice of 10 minutes). When the
* time comes to notify a timer or a timer is first registered the timer is
* offset by this amount to lessen the number of timers firing at the same
* time. this._timerInterval is in milliseconds, whereas the lastUpdateTime is
* in seconds so this._timerInterval is divided by 1000.
*/
get _fudge() { return Math.round(Math.random() * this._timerInterval / 1000); },
/**
* See nsIObserver.idl
*/
observe: function TM_observe(aSubject, aTopic, aData) {
var os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
switch (aTopic) {
case "profile-after-change":
os.addObserver(this, "xpcom-shutdown", false);
this._start();
break;
case "xpcom-shutdown":
os.removeObserver(this, "xpcom-shutdown");
// Release everything we hold onto.
this._timer.cancel();
this._timer = null;
for (var timerID in this._timers)
delete this._timers[timerID];
this._timers = null;
break;
}
},
_start: function TM__start() {
this._timerInterval = getPref("getIntPref", "app.update.timer", 600000);
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this._timer.initWithCallback(this, this._timerInterval,
Ci.nsITimer.TYPE_REPEATING_SLACK);
},
/**
* Called when the checking timer fires.
* @param timer
* The checking timer that fired.
*/
notify: function TM_notify(timer) {
var prefLastUpdate;
var lastUpdateTime;
var now = Math.round(Date.now() / 1000);
var catMan = Cc["@mozilla.org/categorymanager;1"].
getService(Ci.nsICategoryManager);
var entries = catMan.enumerateCategory(CATEGORY_UPDATE_TIMER);
while (entries.hasMoreElements()) {
let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
let value = catMan.getCategoryEntry(CATEGORY_UPDATE_TIMER, entry);
let [cid, method, timerID, prefInterval, defaultInterval] = value.split(",");
defaultInterval = parseInt(defaultInterval);
// cid and method are validated below when calling notify.
if (!timerID || !defaultInterval || isNaN(defaultInterval)) {
LOG("TimerManager", "notify - update-timer category registered" +
(cid ? " for " + cid : "") + " without required parameters - " +
"skipping");
continue;
}
let interval = getPref("getIntPref", prefInterval, defaultInterval);
prefLastUpdate = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/,
timerID);
if (gPref.prefHasUserValue(prefLastUpdate)) {
lastUpdateTime = gPref.getIntPref(prefLastUpdate);
}
else {
lastUpdateTime = now + this._fudge;
gPref.setIntPref(prefLastUpdate, lastUpdateTime);
continue;
}
if ((now - lastUpdateTime) > interval) {
try {
Components.classes[cid][method](Ci.nsITimerCallback).notify(timer);
LOG("TimerManager", "notify - notified " + cid);
}
catch (e) {
LOG("TimerManager", "notify - error notifying component id: " +
cid + " ,error: " + e);
}
lastUpdateTime = now + this._fudge;
gPref.setIntPref(prefLastUpdate, lastUpdateTime);
}
}
for (var timerID in this._timers) {
var timerData = this._timers[timerID];
if ((now - timerData.lastUpdateTime) > timerData.interval) {
if (timerData.callback instanceof Ci.nsITimerCallback) {
try {
timerData.callback.notify(timer);
LOG("TimerManager", "notify - notified timerID: " + timerID);
}
catch (e) {
LOG("TimerManager", "notify - error notifying timerID: " + timerID +
", error: " + e);
}
}
else {
LOG("TimerManager", "notify - timerID: " + timerID + " doesn't " +
"implement nsITimerCallback - skipping");
}
lastUpdateTime = now + this._fudge;
timerData.lastUpdateTime = lastUpdateTime;
prefLastUpdate = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, timerID);
gPref.setIntPref(prefLastUpdate, lastUpdateTime);
}
}
},
/**
* See nsIUpdateService.idl
*/
registerTimer: function TM_registerTimer(id, callback, interval) {
LOG("TimerManager", "registerTimer - id: " + id);
var prefLastUpdate = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, id);
var lastUpdateTime;
if (gPref.prefHasUserValue(prefLastUpdate)) {
lastUpdateTime = gPref.getIntPref(prefLastUpdate);
} else {
lastUpdateTime = Math.round(Date.now() / 1000) + this._fudge;
gPref.setIntPref(prefLastUpdate, lastUpdateTime);
}
this._timers[id] = { callback : callback,
interval : interval,
lastUpdateTime : lastUpdateTime };
},
classDescription: "Timer Manager",
contractID: "@mozilla.org/updates/timer-manager;1",
classID: Components.ID("{B322A5C0-A419-484E-96BA-D7182163899F}"),
_xpcom_categories: [{ category: "profile-after-change" }],
QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdateTimerManager,
Ci.nsITimerCallback,
Ci.nsIObserver])
};
#ifdef MOZ_UPDATER
function NSGetModule(compMgr, fileSpec)
XPCOMUtils.generateModule([UpdateService, Checker, UpdatePrompt, TimerManager, UpdateManager]);
#else
function NSGetModule(compMgr, fileSpec)
XPCOMUtils.generateModule([TimerManager]);
#endif
#if 0
/**
@ -3316,4 +3382,4 @@ function stackTrace(aArguments, aMaxCount) {
function dumpFile(file) {
dump("*** file = " + file.path + ", exists = " + file.exists() + "\n");
}
#endif
#endif

Просмотреть файл

@ -174,7 +174,6 @@ function startAUS() {
QueryInterface(AUS_Ci.nsIObserver);
var os = AUS_Cc["@mozilla.org/observer-service;1"].
getService(AUS_Ci.nsIObserverService);
os.notifyObservers(null, "profile-after-change", null);
os.notifyObservers(null, "final-ui-startup", null);
}