keeweb/app/scripts/comp/app/usb-listener.js

111 lines
3.0 KiB
JavaScript

import { Events } from 'framework/events';
import { Logger } from 'util/logger';
import { Launcher } from 'comp/launcher';
import { AppSettingsModel } from 'models/app-settings-model';
import { YubiKeyVendorId } from 'const/hardware';
import { Features } from 'util/features';
const logger = new Logger('usb-listener');
const UsbListener = {
supported: Features.isDesktop,
attachedYubiKeys: [],
init() {
if (!this.supported) {
return;
}
AppSettingsModel.on('change:enableUsb', (model, enabled) => {
if (enabled) {
this.start();
} else {
this.stop();
}
});
if (AppSettingsModel.enableUsb) {
this.start();
}
},
start() {
logger.info('Starting USB listener');
if (this.usb) {
this.stop();
}
try {
const ts = logger.ts();
this.usb = Launcher.reqNative('usb');
this.listen();
this.attachedYubiKeys = this.usb
.getDeviceList()
.filter(this.isYubiKey)
.map((device) => ({ device }));
if (this.attachedYubiKeys.length > 0) {
logger.info(`${this.attachedYubiKeys.length} YubiKey(s) found`, logger.ts(ts));
Events.emit('usb-devices-changed');
}
} catch (e) {
logger.error('Error loading USB module', e);
}
},
stop() {
logger.info('Stopping USB listener');
if (this.usb) {
if (this.attachedYubiKeys.length) {
this.attachedYubiKeys = [];
Events.emit('usb-devices-changed');
}
this.usb.off('attach', UsbListener.deviceAttached);
this.usb.off('detach', UsbListener.deviceDetached);
this.usb = null;
}
},
listen() {
this.usb.on('attach', UsbListener.deviceAttached);
this.usb.on('detach', UsbListener.deviceDetached);
},
deviceAttached(device) {
if (UsbListener.isYubiKey(device)) {
UsbListener.attachedYubiKeys.push({ device });
logger.info(`YubiKey attached, total: ${UsbListener.attachedYubiKeys.length}`, device);
Events.emit('usb-devices-changed');
}
},
deviceDetached(device) {
if (UsbListener.isYubiKey(device)) {
const index = UsbListener.attachedYubiKeys.findIndex(
(yk) => yk.device.deviceAddress === device.deviceAddress
);
if (index >= 0) {
UsbListener.attachedYubiKeys.splice(index, 1);
logger.info(
`YubiKey detached, total: ${UsbListener.attachedYubiKeys.length}`,
device
);
Events.emit('usb-devices-changed');
}
}
},
isYubiKey(device) {
return device.deviceDescriptor.idVendor === YubiKeyVendorId;
}
};
export { UsbListener };