mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-17 12:47:30 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
21
toolkit/components/timermanager/moz.build
Normal file
21
toolkit/components/timermanager/moz.build
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPIDL_MODULE = 'update'
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIUpdateTimerManager.idl',
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'nsUpdateTimerManager.js',
|
||||
'nsUpdateTimerManager.manifest',
|
||||
]
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Toolkit', 'Application Update')
|
||||
54
toolkit/components/timermanager/nsIUpdateTimerManager.idl
Normal file
54
toolkit/components/timermanager/nsIUpdateTimerManager.idl
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#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);
|
||||
};
|
||||
339
toolkit/components/timermanager/nsUpdateTimerManager.js
Normal file
339
toolkit/components/timermanager/nsUpdateTimerManager.js
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
||||
Components.utils.import("resource://gre/modules/Services.jsm", this);
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
const PREF_APP_UPDATE_LASTUPDATETIME_FMT = "app.update.lastUpdateTime.%ID%";
|
||||
const PREF_APP_UPDATE_TIMERMINIMUMDELAY = "app.update.timerMinimumDelay";
|
||||
const PREF_APP_UPDATE_TIMERFIRSTINTERVAL = "app.update.timerFirstInterval";
|
||||
const PREF_APP_UPDATE_LOG = "app.update.log";
|
||||
|
||||
const CATEGORY_UPDATE_TIMER = "update-timer";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gLogEnabled", function tm_gLogEnabled() {
|
||||
return getPref("getBoolPref", PREF_APP_UPDATE_LOG, false);
|
||||
});
|
||||
|
||||
/**
|
||||
* 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 Services.prefs[func](preference);
|
||||
} catch (e) {
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a string to the error console.
|
||||
* @param string
|
||||
* The string to write to the error console.
|
||||
*/
|
||||
function LOG(string) {
|
||||
if (gLogEnabled) {
|
||||
dump("*** UTM:SVC " + string + "\n");
|
||||
Services.console.logStringMessage("UTM:SVC " + string);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A manager for timers. Manages timers that fire over long periods of time
|
||||
* (e.g. days, weeks, months).
|
||||
* @constructor
|
||||
*/
|
||||
function TimerManager() {
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
}
|
||||
TimerManager.prototype = {
|
||||
/**
|
||||
* The Checker Timer
|
||||
*/
|
||||
_timer: null,
|
||||
|
||||
/**
|
||||
* The Checker Timer minimum delay interval as specified by the
|
||||
* app.update.timerMinimumDelay pref. If the app.update.timerMinimumDelay
|
||||
* pref doesn't exist this will default to 120000.
|
||||
*/
|
||||
_timerMinimumDelay: null,
|
||||
|
||||
/**
|
||||
* The set of registered timers.
|
||||
*/
|
||||
_timers: { },
|
||||
|
||||
/**
|
||||
* See nsIObserver.idl
|
||||
*/
|
||||
observe: function TM_observe(aSubject, aTopic, aData) {
|
||||
// Prevent setting the timer interval to a value of less than 30 seconds.
|
||||
var minInterval = 30000;
|
||||
// Prevent setting the first timer interval to a value of less than 10
|
||||
// seconds.
|
||||
var minFirstInterval = 10000;
|
||||
switch (aTopic) {
|
||||
case "utm-test-init":
|
||||
// Enforce a minimum timer interval of 500 ms for tests and fall through
|
||||
// to profile-after-change to initialize the timer.
|
||||
minInterval = 500;
|
||||
minFirstInterval = 500;
|
||||
case "profile-after-change":
|
||||
this._timerMinimumDelay = Math.max(1000 * getPref("getIntPref", PREF_APP_UPDATE_TIMERMINIMUMDELAY, 120),
|
||||
minInterval);
|
||||
// Prevent the timer delay between notifications to other consumers from
|
||||
// being greater than 5 minutes which is 300000 milliseconds.
|
||||
this._timerMinimumDelay = Math.min(this._timerMinimumDelay, 300000);
|
||||
// Prevent the first interval from being less than the value of minFirstInterval
|
||||
let firstInterval = Math.max(getPref("getIntPref", PREF_APP_UPDATE_TIMERFIRSTINTERVAL,
|
||||
30000), minFirstInterval);
|
||||
// Prevent the first interval from being greater than 2 minutes which is
|
||||
// 120000 milliseconds.
|
||||
firstInterval = Math.min(firstInterval, 120000);
|
||||
// Cancel the timer if it has already been initialized. This is primarily
|
||||
// for tests.
|
||||
this._canEnsureTimer = true;
|
||||
this._ensureTimer(firstInterval);
|
||||
break;
|
||||
case "xpcom-shutdown":
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
|
||||
// Release everything we hold onto.
|
||||
this._cancelTimer();
|
||||
for (var timerID in this._timers) {
|
||||
delete this._timers[timerID];
|
||||
}
|
||||
this._timers = null;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the checking timer fires.
|
||||
*
|
||||
* We only fire one notification each time, so that the operations are
|
||||
* staggered. We don't want too many to happen at once, which could
|
||||
* negatively impact responsiveness.
|
||||
*
|
||||
* @param timer
|
||||
* The checking timer that fired.
|
||||
*/
|
||||
notify: function TM_notify(timer) {
|
||||
var nextDelay = null;
|
||||
function updateNextDelay(delay) {
|
||||
if (nextDelay === null || delay < nextDelay) {
|
||||
nextDelay = delay;
|
||||
}
|
||||
}
|
||||
|
||||
// Each timer calls tryFire(), which figures out which is the one that
|
||||
// wanted to be called earliest. That one will be fired; the others are
|
||||
// skipped and will be done later.
|
||||
var now = Math.round(Date.now() / 1000);
|
||||
|
||||
var callbackToFire = null;
|
||||
var earliestIntendedTime = null;
|
||||
var skippedFirings = false;
|
||||
var lastUpdateTime = null;
|
||||
function tryFire(callback, intendedTime) {
|
||||
var selected = false;
|
||||
if (intendedTime <= now) {
|
||||
if (intendedTime < earliestIntendedTime ||
|
||||
earliestIntendedTime === null) {
|
||||
callbackToFire = callback;
|
||||
earliestIntendedTime = intendedTime;
|
||||
selected = true;
|
||||
} else if (earliestIntendedTime !== null) {
|
||||
skippedFirings = true;
|
||||
}
|
||||
}
|
||||
// We do not need to updateNextDelay for the timer that actually fires;
|
||||
// we'll update right after it fires, with the proper intended time.
|
||||
// Note that we might select one, then select another later (with an
|
||||
// earlier intended time); it is still ok that we did not update for
|
||||
// the first one, since if we have skipped firings, the next delay
|
||||
// will be the minimum delay anyhow.
|
||||
if (!selected) {
|
||||
updateNextDelay(intendedTime - now);
|
||||
}
|
||||
}
|
||||
|
||||
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, maxInterval] = 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);
|
||||
// Allow the update-timer category to specify a maximum value to prevent
|
||||
// values larger than desired.
|
||||
maxInterval = parseInt(maxInterval);
|
||||
if (maxInterval && !isNaN(maxInterval)) {
|
||||
interval = Math.min(interval, maxInterval);
|
||||
}
|
||||
let prefLastUpdate = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/,
|
||||
timerID);
|
||||
// Initialize the last update time to 0 when the preference isn't set so
|
||||
// the timer will be notified soon after a new profile's first use.
|
||||
lastUpdateTime = getPref("getIntPref", prefLastUpdate, 0);
|
||||
|
||||
// If the last update time is greater than the current time then reset
|
||||
// it to 0 and the timer manager will correct the value when it fires
|
||||
// next for this consumer.
|
||||
if (lastUpdateTime > now) {
|
||||
lastUpdateTime = 0;
|
||||
}
|
||||
|
||||
if (lastUpdateTime == 0) {
|
||||
Services.prefs.setIntPref(prefLastUpdate, lastUpdateTime);
|
||||
}
|
||||
|
||||
tryFire(function () {
|
||||
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;
|
||||
Services.prefs.setIntPref(prefLastUpdate, lastUpdateTime);
|
||||
updateNextDelay(lastUpdateTime + interval - now);
|
||||
}, lastUpdateTime + interval);
|
||||
}
|
||||
|
||||
for (let _timerID in this._timers) {
|
||||
let timerID = _timerID; // necessary for the closure to work properly
|
||||
let timerData = this._timers[timerID];
|
||||
// If the last update time is greater than the current time then reset
|
||||
// it to 0 and the timer manager will correct the value when it fires
|
||||
// next for this consumer.
|
||||
if (timerData.lastUpdateTime > now) {
|
||||
let prefLastUpdate = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, timerID);
|
||||
timerData.lastUpdateTime = 0;
|
||||
Services.prefs.setIntPref(prefLastUpdate, timerData.lastUpdateTime);
|
||||
}
|
||||
tryFire(function () {
|
||||
if (timerData.callback && timerData.callback.notify) {
|
||||
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;
|
||||
timerData.lastUpdateTime = lastUpdateTime;
|
||||
let prefLastUpdate = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, timerID);
|
||||
Services.prefs.setIntPref(prefLastUpdate, lastUpdateTime);
|
||||
updateNextDelay(timerData.lastUpdateTime + timerData.interval - now);
|
||||
}, timerData.lastUpdateTime + timerData.interval);
|
||||
}
|
||||
|
||||
if (callbackToFire) {
|
||||
callbackToFire();
|
||||
}
|
||||
|
||||
if (nextDelay !== null) {
|
||||
if (skippedFirings) {
|
||||
timer.delay = this._timerMinimumDelay;
|
||||
} else {
|
||||
timer.delay = Math.max(nextDelay * 1000, this._timerMinimumDelay);
|
||||
}
|
||||
this.lastTimerReset = Date.now();
|
||||
} else {
|
||||
this._cancelTimer();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts the timer, if necessary, and ensures that it will fire soon enough
|
||||
* to happen after time |interval| (in milliseconds).
|
||||
*/
|
||||
_ensureTimer: function (interval) {
|
||||
if (!this._canEnsureTimer) {
|
||||
return;
|
||||
}
|
||||
if (!this._timer) {
|
||||
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this._timer.initWithCallback(this, interval,
|
||||
Ci.nsITimer.TYPE_REPEATING_SLACK);
|
||||
this.lastTimerReset = Date.now();
|
||||
} else if (Date.now() + interval < this.lastTimerReset + this._timer.delay) {
|
||||
this._timer.delay = Math.max(this.lastTimerReset + interval - Date.now(), 0);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Stops the timer, if it is running.
|
||||
*/
|
||||
_cancelTimer: function () {
|
||||
if (this._timer) {
|
||||
this._timer.cancel();
|
||||
this._timer = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* See nsIUpdateTimerManager.idl
|
||||
*/
|
||||
registerTimer: function TM_registerTimer(id, callback, interval) {
|
||||
LOG("TimerManager:registerTimer - id: " + id);
|
||||
if (id in this._timers && callback != this._timers[id].callback) {
|
||||
LOG("TimerManager:registerTimer - Ignoring second registration for " + id);
|
||||
return;
|
||||
}
|
||||
let prefLastUpdate = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, id);
|
||||
// Initialize the last update time to 0 when the preference isn't set so
|
||||
// the timer will be notified soon after a new profile's first use.
|
||||
let lastUpdateTime = getPref("getIntPref", prefLastUpdate, 0);
|
||||
let now = Math.round(Date.now() / 1000);
|
||||
if (lastUpdateTime > now) {
|
||||
lastUpdateTime = 0;
|
||||
}
|
||||
if (lastUpdateTime == 0) {
|
||||
Services.prefs.setIntPref(prefLastUpdate, lastUpdateTime);
|
||||
}
|
||||
this._timers[id] = {callback: callback,
|
||||
interval: interval,
|
||||
lastUpdateTime: lastUpdateTime};
|
||||
|
||||
this._ensureTimer(interval * 1000);
|
||||
},
|
||||
|
||||
classID: Components.ID("{B322A5C0-A419-484E-96BA-D7182163899F}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdateTimerManager,
|
||||
Ci.nsITimerCallback,
|
||||
Ci.nsIObserver])
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TimerManager]);
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
component {B322A5C0-A419-484E-96BA-D7182163899F} nsUpdateTimerManager.js
|
||||
contract @mozilla.org/updates/timer-manager;1 {B322A5C0-A419-484E-96BA-D7182163899F}
|
||||
category profile-after-change nsUpdateTimerManager @mozilla.org/updates/timer-manager;1
|
||||
7
toolkit/components/timermanager/tests/unit/.eslintrc.js
Normal file
7
toolkit/components/timermanager/tests/unit/.eslintrc.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"../../../../../testing/xpcshell/xpcshell.eslintrc.js"
|
||||
]
|
||||
};
|
||||
|
|
@ -0,0 +1,519 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/* General Update Timer Manager Tests */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { classes: Cc, interfaces: Ci, manager: Cm, results: Cr,
|
||||
utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const CATEGORY_UPDATE_TIMER = "update-timer";
|
||||
|
||||
const PREF_APP_UPDATE_TIMERMINIMUMDELAY = "app.update.timerMinimumDelay";
|
||||
const PREF_APP_UPDATE_TIMERFIRSTINTERVAL = "app.update.timerFirstInterval";
|
||||
const PREF_APP_UPDATE_LOG_ALL = "app.update.log.all";
|
||||
const PREF_BRANCH_LAST_UPDATE_TIME = "app.update.lastUpdateTime.";
|
||||
|
||||
const MAIN_TIMER_INTERVAL = 1000; // milliseconds
|
||||
const CONSUMER_TIMER_INTERVAL = 1; // seconds
|
||||
|
||||
const TESTS = [ {
|
||||
desc: "Test Timer Callback 0",
|
||||
timerID: "test0-update-timer",
|
||||
defaultInterval: "bogus",
|
||||
prefInterval: "test0.timer.interval",
|
||||
contractID: "@mozilla.org/test0/timercallback;1",
|
||||
method: "createInstance",
|
||||
classID: Components.ID("9c7ce81f-98bb-4729-adb4-4d0deb0f59e5"),
|
||||
notified: false
|
||||
}, {
|
||||
desc: "Test Timer Callback 1",
|
||||
timerID: "test1-update-timer",
|
||||
defaultInterval: 86400,
|
||||
prefInterval: "test1.timer.interval",
|
||||
contractID: "@mozilla.org/test2/timercallback;1",
|
||||
method: "createInstance",
|
||||
classID: Components.ID("512834f3-05bb-46be-84e0-81d881a140b7"),
|
||||
notified: false
|
||||
}, {
|
||||
desc: "Test Timer Callback 2",
|
||||
timerID: "test2-update-timer",
|
||||
defaultInterval: CONSUMER_TIMER_INTERVAL,
|
||||
prefInterval: "test2.timer.interval",
|
||||
contractID: "@mozilla.org/test2/timercallback;1",
|
||||
method: "createInstance",
|
||||
classID: Components.ID("c8ac5027-8d11-4471-9d7c-fd692501b437"),
|
||||
notified: false
|
||||
}, {
|
||||
desc: "Test Timer Callback 3",
|
||||
timerID: "test3-update-timer",
|
||||
defaultInterval: CONSUMER_TIMER_INTERVAL,
|
||||
prefInterval: "test3.timer.interval",
|
||||
contractID: "@mozilla.org/test3/timercallback;1",
|
||||
method: "createInstance",
|
||||
classID: Components.ID("6b0e79f3-4ab8-414c-8f14-dde10e185727"),
|
||||
notified: false
|
||||
}, {
|
||||
desc: "Test Timer Callback 4",
|
||||
timerID: "test4-update-timer",
|
||||
defaultInterval: CONSUMER_TIMER_INTERVAL,
|
||||
prefInterval: "test4.timer.interval",
|
||||
contractID: "@mozilla.org/test4/timercallback;1",
|
||||
method: "createInstance",
|
||||
classID: Components.ID("2f6b7b92-e40f-4874-bfbb-eeb2412c959d"),
|
||||
notified: false
|
||||
}, {
|
||||
desc: "Test Timer Callback 5",
|
||||
timerID: "test5-update-timer",
|
||||
defaultInterval: 86400,
|
||||
prefInterval: "test5.timer.interval",
|
||||
contractID: "@mozilla.org/test5/timercallback;1",
|
||||
method: "createInstance",
|
||||
classID: Components.ID("8a95f611-b2ac-4c7e-8b73-9748c4839731"),
|
||||
notified: false
|
||||
}, {
|
||||
desc: "Test Timer Callback 6",
|
||||
timerID: "test6-update-timer",
|
||||
defaultInterval: CONSUMER_TIMER_INTERVAL,
|
||||
prefInterval: "test6.timer.interval",
|
||||
contractID: "@mozilla.org/test6/timercallback;1",
|
||||
method: "createInstance",
|
||||
classID: Components.ID("2d091020-e23c-11e2-a28f-0800200c9a66"),
|
||||
notified: false
|
||||
}, {
|
||||
desc: "Test Timer Callback 7",
|
||||
timerID: "test7-update-timer",
|
||||
defaultInterval: 86400,
|
||||
maxInterval: CONSUMER_TIMER_INTERVAL,
|
||||
prefInterval: "test7.timer.interval",
|
||||
contractID: "@mozilla.org/test7/timercallback;1",
|
||||
method: "createInstance",
|
||||
classID: Components.ID("8e8633ae-1d70-4a7a-8bea-6e1e6c5d7742"),
|
||||
notified: false
|
||||
}, {
|
||||
desc: "Test Timer Callback 8",
|
||||
timerID: "test8-update-timer",
|
||||
defaultInterval: CONSUMER_TIMER_INTERVAL,
|
||||
contractID: "@mozilla.org/test8/timercallback;1",
|
||||
classID: Components.ID("af878d4b-1d12-41f6-9a90-4e687367ecc1"),
|
||||
notified: false,
|
||||
lastUpdateTime: 0
|
||||
}, {
|
||||
desc: "Test Timer Callback 9",
|
||||
timerID: "test9-update-timer",
|
||||
defaultInterval: CONSUMER_TIMER_INTERVAL,
|
||||
contractID: "@mozilla.org/test9/timercallback;1",
|
||||
classID: Components.ID("5136b201-d64c-4328-8cf1-1a63491cc117"),
|
||||
notified: false,
|
||||
lastUpdateTime: 0
|
||||
} ];
|
||||
|
||||
var gUTM;
|
||||
var gNextFunc;
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gPref",
|
||||
"@mozilla.org/preferences-service;1",
|
||||
"nsIPrefBranch");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gCatMan",
|
||||
"@mozilla.org/categorymanager;1",
|
||||
"nsICategoryManager");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gCompReg", function () {
|
||||
return Cm.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
});
|
||||
|
||||
const gTest0TimerCallback = {
|
||||
notify: function T0CB_notify(aTimer) {
|
||||
// This can happen when another notification fails and this timer having
|
||||
// time to fire so check other timers are successful.
|
||||
do_throw("gTest0TimerCallback notify method should not have been called");
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
|
||||
};
|
||||
|
||||
const gTest0Factory = {
|
||||
createInstance: function T0F_createInstance(aOuter, aIID) {
|
||||
if (aOuter == null) {
|
||||
return gTest0TimerCallback.QueryInterface(aIID);
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
};
|
||||
|
||||
const gTest1TimerCallback = {
|
||||
notify: function T1CB_notify(aTimer) {
|
||||
// This can happen when another notification fails and this timer having
|
||||
// time to fire so check other timers are successful.
|
||||
do_throw("gTest1TimerCallback notify method should not have been called");
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITimer])
|
||||
};
|
||||
|
||||
const gTest1Factory = {
|
||||
createInstance: function T1F_createInstance(aOuter, aIID) {
|
||||
if (aOuter == null) {
|
||||
return gTest1TimerCallback.QueryInterface(aIID);
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
};
|
||||
|
||||
const gTest2TimerCallback = {
|
||||
notify: function T2CB_notify(aTimer) {
|
||||
// This can happen when another notification fails and this timer having
|
||||
// time to fire so check other timers are successful.
|
||||
do_throw("gTest2TimerCallback notify method should not have been called");
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
|
||||
};
|
||||
|
||||
const gTest2Factory = {
|
||||
createInstance: function T2F_createInstance(aOuter, aIID) {
|
||||
if (aOuter == null) {
|
||||
return gTest2TimerCallback.QueryInterface(aIID);
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
};
|
||||
|
||||
const gTest3TimerCallback = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
|
||||
};
|
||||
|
||||
const gTest3Factory = {
|
||||
createInstance: function T3F_createInstance(aOuter, aIID) {
|
||||
if (aOuter == null) {
|
||||
return gTest3TimerCallback.QueryInterface(aIID);
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
};
|
||||
|
||||
const gTest4TimerCallback = {
|
||||
notify: function T4CB_notify(aTimer) {
|
||||
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[4].desc, true);
|
||||
TESTS[4].notified = true;
|
||||
finished_test0thru7();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
|
||||
};
|
||||
|
||||
const gTest4Factory = {
|
||||
createInstance: function T4F_createInstance(aOuter, aIID) {
|
||||
if (aOuter == null) {
|
||||
return gTest4TimerCallback.QueryInterface(aIID);
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
};
|
||||
|
||||
const gTest5TimerCallback = {
|
||||
notify: function T5CB_notify(aTimer) {
|
||||
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[5].desc, true);
|
||||
TESTS[5].notified = true;
|
||||
finished_test0thru7();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
|
||||
};
|
||||
|
||||
const gTest5Factory = {
|
||||
createInstance: function T5F_createInstance(aOuter, aIID) {
|
||||
if (aOuter == null) {
|
||||
return gTest5TimerCallback.QueryInterface(aIID);
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
};
|
||||
|
||||
const gTest6TimerCallback = {
|
||||
notify: function T6CB_notify(aTimer) {
|
||||
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[6].desc, true);
|
||||
TESTS[6].notified = true;
|
||||
finished_test0thru7();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
|
||||
};
|
||||
|
||||
const gTest6Factory = {
|
||||
createInstance: function T6F_createInstance(aOuter, aIID) {
|
||||
if (aOuter == null) {
|
||||
return gTest6TimerCallback.QueryInterface(aIID);
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
};
|
||||
|
||||
const gTest7TimerCallback = {
|
||||
notify: function T7CB_notify(aTimer) {
|
||||
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[7].desc, true);
|
||||
TESTS[7].notified = true;
|
||||
finished_test0thru7();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
|
||||
};
|
||||
|
||||
const gTest7Factory = {
|
||||
createInstance: function T7F_createInstance(aOuter, aIID) {
|
||||
if (aOuter == null) {
|
||||
return gTest7TimerCallback.QueryInterface(aIID);
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
};
|
||||
|
||||
const gTest8TimerCallback = {
|
||||
notify: function T8CB_notify(aTimer) {
|
||||
TESTS[8].notified = true;
|
||||
TESTS[8].notifyTime = Date.now();
|
||||
do_execute_soon(function () {
|
||||
check_test8thru9(gTest8TimerCallback);
|
||||
});
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
|
||||
};
|
||||
|
||||
const gTest8Factory = {
|
||||
createInstance: function T8F_createInstance(aOuter, aIID) {
|
||||
if (aOuter == null) {
|
||||
return gTest8TimerCallback.QueryInterface(aIID);
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
};
|
||||
|
||||
const gTest9TimerCallback = {
|
||||
notify: function T9CB_notify(aTimer) {
|
||||
TESTS[9].notified = true;
|
||||
TESTS[9].notifyTime = Date.now();
|
||||
do_execute_soon(function () {
|
||||
check_test8thru9(gTest9TimerCallback);
|
||||
});
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
|
||||
};
|
||||
|
||||
const gTest9Factory = {
|
||||
createInstance: function T9F_createInstance(aOuter, aIID) {
|
||||
if (aOuter == null) {
|
||||
return gTest9TimerCallback.QueryInterface(aIID);
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
};
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
// Set the timer to fire every second
|
||||
gPref.setIntPref(PREF_APP_UPDATE_TIMERMINIMUMDELAY, MAIN_TIMER_INTERVAL / 1000);
|
||||
gPref.setIntPref(PREF_APP_UPDATE_TIMERFIRSTINTERVAL, MAIN_TIMER_INTERVAL);
|
||||
gPref.setBoolPref(PREF_APP_UPDATE_LOG_ALL, true);
|
||||
|
||||
// Remove existing update timers to prevent them from being notified
|
||||
let entries = gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER);
|
||||
while (entries.hasMoreElements()) {
|
||||
let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
|
||||
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, entry, false);
|
||||
}
|
||||
|
||||
gUTM = Cc["@mozilla.org/updates/timer-manager;1"].
|
||||
getService(Ci.nsIUpdateTimerManager).
|
||||
QueryInterface(Ci.nsIObserver);
|
||||
gUTM.observe(null, "utm-test-init", "");
|
||||
|
||||
do_execute_soon(run_test0thru7);
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
gUTM.observe(null, "xpcom-shutdown", "");
|
||||
do_test_finished();
|
||||
}
|
||||
|
||||
function run_test0thru7() {
|
||||
gNextFunc = check_test0thru7;
|
||||
// bogus default interval
|
||||
gCompReg.registerFactory(TESTS[0].classID, TESTS[0].desc,
|
||||
TESTS[0].contractID, gTest0Factory);
|
||||
gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[0].desc,
|
||||
[TESTS[0].contractID, TESTS[0].method,
|
||||
TESTS[0].timerID, TESTS[0].prefInterval,
|
||||
TESTS[0].defaultInterval].join(","), false, true);
|
||||
|
||||
// doesn't implement nsITimerCallback
|
||||
gCompReg.registerFactory(TESTS[1].classID, TESTS[1].desc,
|
||||
TESTS[1].contractID, gTest1Factory);
|
||||
gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[1].desc,
|
||||
[TESTS[1].contractID, TESTS[1].method,
|
||||
TESTS[1].timerID, TESTS[1].prefInterval,
|
||||
TESTS[1].defaultInterval].join(","), false, true);
|
||||
|
||||
// has a last update time of now - 43200 which is half of its interval
|
||||
let lastUpdateTime = Math.round(Date.now() / 1000) - 43200;
|
||||
gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[2].timerID, lastUpdateTime);
|
||||
gCompReg.registerFactory(TESTS[2].classID, TESTS[2].desc,
|
||||
TESTS[2].contractID, gTest2Factory);
|
||||
gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[2].desc,
|
||||
[TESTS[2].contractID, TESTS[2].method,
|
||||
TESTS[2].timerID, TESTS[2].prefInterval,
|
||||
TESTS[2].defaultInterval].join(","), false, true);
|
||||
|
||||
// doesn't have a notify method
|
||||
gCompReg.registerFactory(TESTS[3].classID, TESTS[3].desc,
|
||||
TESTS[3].contractID, gTest3Factory);
|
||||
gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[3].desc,
|
||||
[TESTS[3].contractID, TESTS[3].method,
|
||||
TESTS[3].timerID, TESTS[3].prefInterval,
|
||||
TESTS[3].defaultInterval].join(","), false, true);
|
||||
|
||||
// already has a last update time
|
||||
gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[4].timerID, 1);
|
||||
gCompReg.registerFactory(TESTS[4].classID, TESTS[4].desc,
|
||||
TESTS[4].contractID, gTest4Factory);
|
||||
gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[4].desc,
|
||||
[TESTS[4].contractID, TESTS[4].method,
|
||||
TESTS[4].timerID, TESTS[4].prefInterval,
|
||||
TESTS[4].defaultInterval].join(","), false, true);
|
||||
|
||||
// has an interval preference that overrides the default
|
||||
gPref.setIntPref(TESTS[5].prefInterval, CONSUMER_TIMER_INTERVAL);
|
||||
gCompReg.registerFactory(TESTS[5].classID, TESTS[5].desc,
|
||||
TESTS[5].contractID, gTest5Factory);
|
||||
gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[5].desc,
|
||||
[TESTS[5].contractID, TESTS[5].method,
|
||||
TESTS[5].timerID, TESTS[5].prefInterval,
|
||||
TESTS[5].defaultInterval].join(","), false, true);
|
||||
|
||||
// has a next update time 24 hours from now
|
||||
let nextUpdateTime = Math.round(Date.now() / 1000) + 86400;
|
||||
gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[6].timerID, nextUpdateTime);
|
||||
gCompReg.registerFactory(TESTS[6].classID, TESTS[6].desc,
|
||||
TESTS[6].contractID, gTest6Factory);
|
||||
gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[6].desc,
|
||||
[TESTS[6].contractID, TESTS[6].method,
|
||||
TESTS[6].timerID, TESTS[6].prefInterval,
|
||||
TESTS[6].defaultInterval].join(","), false, true);
|
||||
|
||||
// has a maximum interval set by the value of MAIN_TIMER_INTERVAL
|
||||
gPref.setIntPref(TESTS[7].prefInterval, 86400);
|
||||
gCompReg.registerFactory(TESTS[7].classID, TESTS[7].desc,
|
||||
TESTS[7].contractID, gTest7Factory);
|
||||
gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[7].desc,
|
||||
[TESTS[7].contractID, TESTS[7].method,
|
||||
TESTS[7].timerID, TESTS[7].prefInterval,
|
||||
TESTS[7].defaultInterval,
|
||||
TESTS[7].maxInterval].join(","), false, true);
|
||||
}
|
||||
|
||||
function finished_test0thru7() {
|
||||
if (TESTS[4].notified && TESTS[5].notified && TESTS[6].notified && TESTS[7].notified) {
|
||||
do_execute_soon(gNextFunc);
|
||||
}
|
||||
}
|
||||
|
||||
function check_test0thru7() {
|
||||
Assert.ok(!TESTS[0].notified,
|
||||
"a category registered timer didn't fire due to an invalid " +
|
||||
"default interval");
|
||||
|
||||
Assert.ok(!TESTS[1].notified,
|
||||
"a category registered timer didn't fire due to not implementing " +
|
||||
"nsITimerCallback");
|
||||
|
||||
Assert.ok(!TESTS[2].notified,
|
||||
"a category registered timer didn't fire due to the next update " +
|
||||
"time being in the future");
|
||||
|
||||
Assert.ok(!TESTS[3].notified,
|
||||
"a category registered timer didn't fire due to not having a " +
|
||||
"notify method");
|
||||
|
||||
Assert.ok(TESTS[4].notified,
|
||||
"a category registered timer has fired");
|
||||
|
||||
Assert.ok(TESTS[5].notified,
|
||||
"a category registered timer fired that has an interval " +
|
||||
"preference that overrides a default that wouldn't have fired yet");
|
||||
|
||||
Assert.ok(TESTS[6].notified,
|
||||
"a category registered timer has fired due to the next update " +
|
||||
"time being reset due to a future last update time");
|
||||
|
||||
Assert.ok(gPref.prefHasUserValue(PREF_BRANCH_LAST_UPDATE_TIME +
|
||||
TESTS[4].timerID),
|
||||
"first of two category registered timers last update time has " +
|
||||
"a user value");
|
||||
Assert.ok(gPref.prefHasUserValue(PREF_BRANCH_LAST_UPDATE_TIME +
|
||||
TESTS[5].timerID),
|
||||
"second of two category registered timers last update time has " +
|
||||
"a user value");
|
||||
|
||||
// Remove the category timers that should have failed
|
||||
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[0].desc, true);
|
||||
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[1].desc, true);
|
||||
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[2].desc, true);
|
||||
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[3].desc, true);
|
||||
let entries = gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER);
|
||||
while (entries.hasMoreElements()) {
|
||||
let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
|
||||
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, entry, false);
|
||||
}
|
||||
|
||||
entries = gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER);
|
||||
Assert.ok(!entries.hasMoreElements(),
|
||||
"no " + CATEGORY_UPDATE_TIMER + " categories should still be " +
|
||||
"registered");
|
||||
|
||||
do_execute_soon(run_test8thru9);
|
||||
}
|
||||
|
||||
function run_test8thru9() {
|
||||
gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[8].timerID, 1);
|
||||
gCompReg.registerFactory(TESTS[8].classID, TESTS[8].desc,
|
||||
TESTS[8].contractID, gTest8Factory);
|
||||
gUTM.registerTimer(TESTS[8].timerID, gTest8TimerCallback,
|
||||
TESTS[8].defaultInterval);
|
||||
gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[9].timerID, 1);
|
||||
gCompReg.registerFactory(TESTS[9].classID, TESTS[9].desc,
|
||||
TESTS[9].contractID, gTest9Factory);
|
||||
gUTM.registerTimer(TESTS[9].timerID, gTest9TimerCallback,
|
||||
TESTS[9].defaultInterval);
|
||||
}
|
||||
|
||||
function check_test8thru9(aTestTimerCallback) {
|
||||
aTestTimerCallback.timesCalled = (aTestTimerCallback.timesCalled || 0) + 1;
|
||||
if (aTestTimerCallback.timesCalled < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.ok(TESTS[8].notified,
|
||||
"first registerTimer registered timer should have fired");
|
||||
|
||||
Assert.ok(TESTS[9].notified,
|
||||
"second registerTimer registered timer should have fired");
|
||||
|
||||
// Check that 'staggering' has happened: even though the two events wanted to fire at
|
||||
// the same time, we waited a full MAIN_TIMER_INTERVAL between them.
|
||||
// (to avoid sensitivity to random timing issues, we fudge by a factor of 0.5 here)
|
||||
Assert.ok(Math.abs(TESTS[8].notifyTime - TESTS[9].notifyTime) >=
|
||||
MAIN_TIMER_INTERVAL * 0.5,
|
||||
"staggering between two timers that want to fire at the same " +
|
||||
"time should have occured");
|
||||
|
||||
let time = gPref.getIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[8].timerID);
|
||||
Assert.notEqual(time, 1,
|
||||
"first registerTimer registered timer last update time " +
|
||||
"should have been updated");
|
||||
|
||||
time = gPref.getIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[9].timerID);
|
||||
Assert.notEqual(time, 1,
|
||||
"second registerTimer registered timer last update time " +
|
||||
"should have been updated");
|
||||
|
||||
end_test();
|
||||
}
|
||||
9
toolkit/components/timermanager/tests/unit/xpcshell.ini
Normal file
9
toolkit/components/timermanager/tests/unit/xpcshell.ini
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
[DEFAULT]
|
||||
head =
|
||||
tail =
|
||||
|
||||
[consumerNotifications.js]
|
||||
Loading…
Add table
Add a link
Reference in a new issue