Can Any Desktop Browsers Detect When the Computer Resumes from Sleep

Identify computer has awaken from sleep mode with JS

Browsers are getting increasingly aggressive about managing power consumption, especially from inactive windows or tabs. A quick duckduckgo for "safari settimeout javascript inactive throttle" will give you lots of hits. After a certain amount of time, browsers understandably may disregard your requested timeout interval, add exponential lengthening timeouts, or freeze the javascript entirely. I personally am very glad they do.

I doubt there is a way around this, because any loophole would be exploited, and websites would again be to able consume CPU cycles and thus power even when the user hasn't looked at that window tab for hours or days.

If there is (or will be someday) a way around this, it will probably look something like how iOS apps work, where apps are frozen but can request to have a background task be woken up for very specific events.

How can I detect if the computer power is suspended in javascript?

I have managed to achieve this by using a javascript interval that checks how much time has passed. If the power is suspended then the time difference between ticks is off.

  <script>
var last = (new Date()).getTime();

setInterval(function(){
var current = (new Date()).getTime();
if (current-last > 3000) {
console.log('power was suspended');
}
last = current;

}, 1000);
</script>

chrome detect when computer wakes up from idle state

Chrome has an idle API:

chrome.idle.onStateChanged(function(state) {
if (state == 'active') {
console.log('State is now active');
}
});

You can read about it here: https://developer.chrome.com/apps/idle

Start calling js function when PC wakeup from sleep mode

You can detect disruptions in the JS timeline (e.g. laptop sleep, alert windows that block JS excecution, debugger statements that open the debugger) by comparing change in wall time to expected timer delay. For example:

var SAMPLE_RATE = 3000; // 3 seconds
var lastSample = Date.now();
function sample() {
if (Date.now() - lastSample >= SAMPLE_RATE * 2) {
// Code here will only run if the timer is delayed by more 2X the sample rate
// (e.g. if the laptop sleeps for more than 3-6 seconds)
}
lastSample = Date.now();
setTimeout(sample, SAMPLE_RATE);
}

sample();

Log a user out of a website when they put their computer to sleep

UPDATE

Regarding the WebSocket request, I assume you're using Laravel WebSockets with pusher. Pusher.io does not support timeout, you can read this support article "Do you plan to add a connection timeout feature to the Channels pusher-js client library?". You can test it out if you enable Laravel debug mode (APP_DEBUG=true inside .env) and beggin laravel-websockets from terminal (php artisan websockets:serve) so you can see the output log events. If you try to close the laptop lid or set computer to hibernation mode (sleep), you won't see any messages regarding this event. You cannot do it with the pusher protocol. There is the member_removed Presence event, but that triggers only when you close the tab or you logout. Of course you can trigger your client custom event to the presence channel, but to do that you also need a timer setup to the client side and you'll have to create a service provider for the laravel-websockets server like this github issue "Exist a way to implement webhooks?".

Some people have suggested in other similar questions:

...

  • To have a timer running on the front end (we do, it just stops when you close the laptop lid)

That happens because client timers halt execution on hibernation, thus they continue from where they were before. But if you use a date variable to save the time, that variable will not get updated when the computer goes to hibernation, thus you'll know when it goes out from sleep by checking that date variable which in compare to current time will have significant difference and will be greater than the timer interval.

Implementing time logic in client

You can also see this implementation to this related Q/A: Can any desktop browsers detect when the computer resumes from sleep?

You can setup a timer in the client to run each minute. We won't rely on the timer interval, but instead that timer will check an outer scope date variable if the time span since last timer is greater than 15 minutes; if it is, then that means that the browser/JS halted execution for some reason, possibly hibernation of the device (sleep) and then you redirect the user to the logout route.

Example JS client code:

// Set a variable to check previous time
let clientSession = new Date;

// Setup the client session checking timer
let clientSessionTimer = setInterval(() => {
const now = new Date;
// Get how many seconds have passed since last check
const secondsSpan = (now - clientSession) / 1000;

// If the 1 minute timer has exceeded 15 minutes trigger logout and clear timer
if (secondsSpan > (60 * 15)) {
// For some reason JS halted execution, so we'll proceed with logging out
clearInterval(clientSessionTimer);
window.location.href = '/logout/session'
} else {
// The timer runs as it should, update the clientSession time
clientSession = now;
}

}, 1000 * 60);

You can check this simple example but using 1 second timer with 15 seconds logout here. Best to test it on a laptop with closing the lid and then open it again after 15 seconds a minute of two, because if you have many programs running, the computer takes some time to save memory state so to complete hibernation mode and halt execution.

Web Workers Example

You can even use Web Workers API to setup a web worker to be much safer:

Page JS code:

const logoutWorker = new Worker('logoutWorker.js');
logoutWorker.onmessage = function (ev) {

if (ev && ev.data === 'wakeup') {
logoutWorker.terminate();
// window.location.href = '/logout/session'
} else {
// The timer runs as it should, nothing to do
}
}

Web worker logoutWorker.js code:

let clientSession = new Date();

let clientSessionTimer = setInterval(() => {
const now = new Date;
const secondsSpan = (now - clientSession) / 1000;

if (secondsSpan > 15) {
postMessage('wakeup'); // Send a message wakeup to the worker page
clearInterval(clientSessionTimer); // Clear the timer
} else {
clientSession = now; // Update the clientSession timer variable
postMessage('update'); // And post a message to the page ONLY IF needed
}
}, 1000);

You can also check the Web Worker example with the same 15 seconds timer here.

What happens to setTimeout when the computer goes to sleep?

As far as I've tested, it just stops and resumes after the computer wakes up. When the computer awakes the setInterval/setTimeout is unaware that any time passed.

I don't think you should rely on the accuracy of setTimeout/Interval for time critical stuff. For google chrome I discovered recently that any timeout/interval (that is shorter than 1s) will be slowed down to once a second if the tab where it's activated looses focus.

Apart from that the accuracy of timeouts/intervals is dependent on other functions running etc. In short: it's not very accurate.

So using interval and timeouts, checking the time against a starttime within the function started by it would give you better accuracy. Now if you start at 12:00, the computer goes to sleep and wakes up at 16:13 or so, checking 16:13 against 12:00 you are certain you have to renew the token. An example of using time comparison can be found here



Related Topics



Leave a reply



Submit