VulpesOS/gaia/apps/email/js/ext/wakelocks.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

138 lines
4.8 KiB
JavaScript
Executable file

define(function(require) {
'use strict';
var $router = require('./worker-router');
var sendMessage = $router.registerCallbackType('wakelocks');
/**
* SmartWakeLock: A renewable, failsafe Wake Lock manager.
*
* Example:
* var lock = new SmartWakeLock({ locks: ['cpu', 'screen'] });
* // do things; if we do nothing, the lock expires eventually.
* lock.renew(); // Keep the lock around for a while longer.
* // Some time later...
* lock.unlock();
*
* Grab a set of wake locks, holding on to them until either a
* failsafe timeout expires, or you release them.
*
* @param {int} opts.timeout
* Timeout, in millseconds, to hold the lock if you fail to call
* .unlock().
* @param {String[]} opts.locks
* Array of strings, e.g. ['cpu', 'wifi'], representing the locks
* you wish to acquire.
*/
function SmartWakeLock(opts) {
this.timeoutMs = opts.timeout || SmartWakeLock.DEFAULT_TIMEOUT_MS;
var locks = this.locks = {}; // map of lockType -> wakeLockInstance
this._timeout = null; // The ID returned from our setTimeout.
// Since we have to fling things over the bridge, requesting a
// wake lock here is asynchronous. Using a Promise to track when
// we've successfully acquired the locks (and blocking on it in
// the methods on this class) ensures that folks can ignore the
// ugly asynchronous parts and not worry about when things happen
// under the hood.
this._readyPromise = Promise.all(opts.locks.map(function(type) {
return new Promise(function(resolve, reject) {
sendMessage('requestWakeLock', [type], function(lockId) {
locks[type] = lockId;
resolve();
});
});
})).then(function() {
this._debug('Acquired', this, 'for', this.timeoutMs + 'ms');
// For simplicity of implementation, we reuse the `renew` method
// here to add the initial `opts.timeout` to the unlock clock.
this.renew(); // Start the initial timeout.
}.bind(this));
}
SmartWakeLock.DEFAULT_TIMEOUT_MS = 45000;
SmartWakeLock.prototype = {
/**
* Renew the timeout, if you're certain that you still need to hold
* the locks longer.
*/
renew: function(/* optional */ reason, callback) {
if (typeof reason === 'function') {
callback = reason;
reason = null;
}
// Wait until we've successfully acquired the wakelocks, then...
this._readyPromise.then(function() {
// If we've already set a timeout, we'll clear that first.
// (Otherwise, we're just loading time on for the first time,
// and don't need to clear or log anything.)
if (this._timeout) {
clearTimeout(this._timeout);
this._debug('Renewing', this, 'for another', this.timeoutMs + 'ms' +
(reason ? ' (reason: ' + reason + ')' : '') + ',',
'would have expired in ' +
(this.timeoutMs - (Date.now() - this._timeLastRenewed)) +
'ms if not renewed.');
}
this._timeLastRenewed = Date.now(); // Solely for debugging.
this._timeout = setTimeout(function() {
this._debug('*** Unlocking', this,
'due to a TIMEOUT. Did you remember to unlock? ***');
this.unlock.bind(this);
}.bind(this), this.timeoutMs);
callback && callback();
}.bind(this));
},
/**
* Unlock all the locks. This happens asynchronously behind the
* scenes; if you want to block on completion, hook onto the
* Promise returned from this function.
*/
unlock: function(/* optional */ reason) {
// Make sure weve been locked before we try to unlock. Also,
// return the promise, throughout the chain of calls here, so
// that listeners can listen for completion if they need to.
return this._readyPromise.then(function() {
var desc = this.toString();
var locks = this.locks;
this.locks = {}; // Clear the locks.
clearTimeout(this._timeout);
// Wait for all of them to successfully unlock.
return Promise.all(Object.keys(locks).map(function(type) {
return new Promise(function(resolve, reject) {
sendMessage('unlock', [locks[type]], function(lockId) {
resolve();
});
});
})).then(function() {
this._debug('Unlocked', desc + '.',
(reason ? 'Reason: ' + reason : ''));
}.bind(this));
}.bind(this));
},
toString: function() {
return Object.keys(this.locks).join('+') || '(no locks)';
},
_debug: function() {
var args = Array.slice(arguments);
console.log.apply(console, ['SmartWakeLock:'].concat(args));
}
};
return {
SmartWakeLock: SmartWakeLock
};
});