1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00
metamask-extension/app/scripts/controllers/app-state.js
Mark Stacey 3d0ffc50f8
Minimize inactive timer resets (#8531)
The inactive timer was being reset upon any change to the preferences
store. The intent was only to update the timer when the auto-lock
timeout had changed, so the subscription was updated to only update in
those cases.

There are no indications that this had any effect upon the user. It
looks like the preferences store never updates while the extension is
unattended, so in practice this may have been harmless. It was still
pointless however. This also protects against the possibility of the
preferences store being updated while unattended at some point in the
future.
2020-05-05 20:30:50 -03:00

147 lines
3.7 KiB
JavaScript

import ObservableStore from 'obs-store'
import EventEmitter from 'events'
export default class AppStateController extends EventEmitter {
/**
* @constructor
* @param opts
*/
constructor (opts = {}) {
const {
addUnlockListener,
isUnlocked,
initState,
onInactiveTimeout,
showUnlockRequest,
preferencesStore,
} = opts
const { preferences } = preferencesStore.getState()
super()
this.onInactiveTimeout = onInactiveTimeout || (() => {})
this.store = new ObservableStore(Object.assign({
timeoutMinutes: 0,
connectedStatusPopoverHasBeenShown: true,
}, initState))
this.timer = null
this.isUnlocked = isUnlocked
this.waitingForUnlock = []
addUnlockListener(this.handleUnlock.bind(this))
this._showUnlockRequest = showUnlockRequest
preferencesStore.subscribe(({ preferences }) => {
const currentState = this.store.getState()
if (currentState.timeoutMinutes !== preferences.autoLockTimeLimit) {
this._setInactiveTimeout(preferences.autoLockTimeLimit)
}
})
this._setInactiveTimeout(preferences.autoLockTimeLimit)
}
/**
* Get a Promise that resolves when the extension is unlocked.
* This Promise will never reject.
*
* @param {boolean} shouldShowUnlockRequest - Whether the extension notification
* popup should be opened.
* @returns {Promise<void>} A promise that resolves when the extension is
* unlocked, or immediately if the extension is already unlocked.
*/
getUnlockPromise (shouldShowUnlockRequest) {
return new Promise((resolve) => {
if (this.isUnlocked()) {
resolve()
} else {
this.waitForUnlock(resolve, shouldShowUnlockRequest)
}
})
}
/**
* Adds a Promise's resolve function to the waitingForUnlock queue.
* Also opens the extension popup if specified.
*
* @param {Promise.resolve} resolve - A Promise's resolve function that will
* be called when the extension is unlocked.
* @param {boolean} shouldShowUnlockRequest - Whether the extension notification
* popup should be opened.
*/
waitForUnlock (resolve, shouldShowUnlockRequest) {
this.waitingForUnlock.push({ resolve })
this.emit('updateBadge')
if (shouldShowUnlockRequest) {
this._showUnlockRequest()
}
}
/**
* Drains the waitingForUnlock queue, resolving all the related Promises.
*/
handleUnlock () {
if (this.waitingForUnlock.length > 0) {
while (this.waitingForUnlock.length > 0) {
this.waitingForUnlock.shift().resolve()
}
this.emit('updateBadge')
}
}
/**
* Record that the user has seen the connected status info popover
*/
setConnectedStatusPopoverHasBeenShown () {
this.store.updateState({
connectedStatusPopoverHasBeenShown: true,
})
}
/**
* Sets the last active time to the current time
* @returns {void}
*/
setLastActiveTime () {
this._resetTimer()
}
/**
* Sets the inactive timeout for the app
* @param {number} timeoutMinutes - the inactive timeout in minutes
* @returns {void}
* @private
*/
_setInactiveTimeout (timeoutMinutes) {
this.store.updateState({
timeoutMinutes,
})
this._resetTimer()
}
/**
* Resets the internal inactive timer
*
* If the {@code timeoutMinutes} state is falsy (i.e., zero) then a new
* timer will not be created.
*
* @returns {void}
* @private
*/
_resetTimer () {
const { timeoutMinutes } = this.store.getState()
if (this.timer) {
clearTimeout(this.timer)
}
if (!timeoutMinutes) {
return
}
this.timer = setTimeout(() => this.onInactiveTimeout(), timeoutMinutes * 60 * 1000)
}
}