From 0037974a9f5e6bb6e419380612d9597967a3a550 Mon Sep 17 00:00:00 2001 From: Chris H-C Date: Wed, 9 Oct 2019 20:18:55 +0000 Subject: [PATCH] Bug 1579522 - Allow skipping first update timer interval r=kmag The UpdateTimerManager has an undocumented behaviour for firing its listeners very soon after first registration (about 10min into the first session). Let's document that behaviour, and make it optional. Differential Revision: https://phabricator.services.mozilla.com/D46292 --HG-- extra : moz-landing-system : lando --- .../timermanager/UpdateTimerManager.jsm | 9 +++- .../timermanager/nsIUpdateTimerManager.idl | 8 +++- .../timermanager/tests/unit/test_skipFirst.js | 45 +++++++++++++++++++ .../timermanager/tests/unit/xpcshell.ini | 1 + 4 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 toolkit/components/timermanager/tests/unit/test_skipFirst.js diff --git a/toolkit/components/timermanager/UpdateTimerManager.jsm b/toolkit/components/timermanager/UpdateTimerManager.jsm index 5075cc7b063e..b31889b27fa5 100644 --- a/toolkit/components/timermanager/UpdateTimerManager.jsm +++ b/toolkit/components/timermanager/UpdateTimerManager.jsm @@ -342,8 +342,10 @@ TimerManager.prototype = { /** * See nsIUpdateTimerManager.idl */ - registerTimer: function TM_registerTimer(id, callback, interval) { - LOG(`TimerManager:registerTimer - timerID: ${id} interval: ${interval}`); + registerTimer: function TM_registerTimer(id, callback, interval, skipFirst) { + LOG( + `TimerManager:registerTimer - timerID: ${id} interval: ${interval} skipFirst: ${skipFirst}` + ); if (this._timers === null) { // Use normal logging since reportError is not available while shutting // down. @@ -370,6 +372,9 @@ TimerManager.prototype = { lastUpdateTime = 0; } if (lastUpdateTime == 0) { + if (skipFirst) { + lastUpdateTime = now; + } Services.prefs.setIntPref(prefLastUpdate, lastUpdateTime); } this._timers[id] = { callback, interval, lastUpdateTime }; diff --git a/toolkit/components/timermanager/nsIUpdateTimerManager.idl b/toolkit/components/timermanager/nsIUpdateTimerManager.idl index 763898e81af7..c0ac4266f680 100644 --- a/toolkit/components/timermanager/nsIUpdateTimerManager.idl +++ b/toolkit/components/timermanager/nsIUpdateTimerManager.idl @@ -19,7 +19,8 @@ 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. + * restarts and can handle intervals of long durations. The callback will be + * called soon after the first registration unless you ask to skip it. * @param id * An id that identifies the interval, used for persistence * @param callback @@ -27,6 +28,8 @@ interface nsIUpdateTimerManager : nsISupports * expires * @param interval * The length of time, in seconds, of the interval + * @param skipFirst + * Whether to skip the initial callback on first registration. * * Note: to avoid having to instantiate a component to call registerTimer * the component can intead register an update-timer category with comma @@ -46,7 +49,8 @@ interface nsIUpdateTimerManager : nsISupports */ void registerTimer(in AString id, in nsITimerCallback callback, - in unsigned long interval); + in unsigned long interval, + [optional] in boolean skipFirst); /** * Unregister an existing interval from the timer manager. diff --git a/toolkit/components/timermanager/tests/unit/test_skipFirst.js b/toolkit/components/timermanager/tests/unit/test_skipFirst.js new file mode 100644 index 000000000000..a0306ec430b4 --- /dev/null +++ b/toolkit/components/timermanager/tests/unit/test_skipFirst.js @@ -0,0 +1,45 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +"use strict"; + +const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); +const { XPCOMUtils } = ChromeUtils.import( + "resource://gre/modules/XPCOMUtils.jsm" +); + +XPCOMUtils.defineLazyServiceGetter( + this, + "gUpdateTimerManager", + "@mozilla.org/updates/timer-manager;1", + "nsIUpdateTimerManager" +); + +const PREF_APP_UPDATE_LASTUPDATETIME_FMT = "app.update.lastUpdateTime.%ID%"; + +add_task(async function() { + const testId = "test_timer_id"; + const testPref = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, testId); + const testInterval = 100000000; // Just needs to be longer than the test. + + Services.prefs.clearUserPref(testPref); + gUpdateTimerManager.registerTimer( + testId, + {}, + testInterval, + true /* skipFirst */ + ); + let prefValue = Services.prefs.getIntPref(testPref, 0); + Assert.notEqual( + prefValue, + 0, + "Last update time for test timer must not be 0." + ); + let nowSeconds = Date.now() / 1000; // update timer lastUpdate prefs are set in seconds. + Assert.ok( + Math.abs(nowSeconds - prefValue) < 2, + "Last update time for test timer must be now-ish." + ); + + gUpdateTimerManager.unregisterTimer(testId); +}); diff --git a/toolkit/components/timermanager/tests/unit/xpcshell.ini b/toolkit/components/timermanager/tests/unit/xpcshell.ini index a2bc4f6ca6bd..423eb51ae847 100644 --- a/toolkit/components/timermanager/tests/unit/xpcshell.ini +++ b/toolkit/components/timermanager/tests/unit/xpcshell.ini @@ -6,3 +6,4 @@ head = [consumerNotifications.js] +[test_skipFirst.js]