I'm making a Firefox browser extension (note: Chrome extensions and Firefox extensions have very similar APIs) that monitors screentime on certain websites that can be selected by the user. Specifically, the screen time counter should reset every 24 hours at midnight.
The code in question:
let interval = setInterval(update, 1000);
let msTillMidnight = (new Date().setHours(24, 0, 0, 0) - Date.now());
function restart() {
browser.storage.local.get("totalTime").then(res => {
browser.storage.local.set({timeLeft: res["totalTime"]});
});
if (!running) {
running = true;
interval = setInterval(update, 1000);
}
}
new Promise(resolve => setTimeout(resolve, msTillMidnight)).then(() => { // I am aware this is laughably redundant, but in theory it should work exactly the same
restart();
setInterval(restart, 1000 * 60 * 60 * 24); // 1000 ms/second —> 60 s/minute —> 60 m/hour —> 24 h/day
});
I noticed a very odd behavior. After the first midnight after the extension began running, restart
was not called. None of the browser storage vars were updated, nor the interval, not the running
bool. The problem, I assumed, was that the setTimeout
in question was simply not running. However, the next night, the clock had reset!
I don't understand. Is something wrong with my msTillMidnight
variable? Is it because the background page shuts down and won't run any setTimeout
scripts after a while when my computer is asleep at midnight and that the restart
function will only call when my computer is still on or shut down recently? Or maybe, my redundant line of code that beats around the bush instead of a simple setTimeout is somehow causing a bug?
I would love to debug this on my own, but my testing cycles would most likely be 24 hours, which is a little slower than I would prefer...
setTimeout
and setInterval
don't rely on computer's clock. They are timers, so if browser "lost" some time due to computer sleep, the timers will not advance during that time.
You'll need use setInterval
and check date every nn seconds. This however might also fail if extension was suspended.
A be better approach might be to use alarms instead. Specifically, by using when
in alarmInfo
option. However alarms will "catch up" if missed (for example in your case if computer was sleeping for 7 days, when woke up, it will trigger 7 alarms at once)
This should work fine with manifest v2, however manifest v3 doesn't have background processes and it suspends extensions after 15 minutes or so, even alarms won't fire. There are a few work arounds this, none of which is perfect.