mirror of https://github.com/keeweb/keeweb
fixed native module helper
parent
5af7837468
commit
ec7155809b
|
@ -9,11 +9,18 @@ let NativeModules;
|
|||
if (Launcher) {
|
||||
const logger = new Logger('native-module-connector');
|
||||
|
||||
let host;
|
||||
let hostRunning = false;
|
||||
let hostStartPromise;
|
||||
let callId = 0;
|
||||
let promises = {};
|
||||
let ykChalRespCallbacks = {};
|
||||
|
||||
const { ipcRenderer } = Launcher.electron();
|
||||
ipcRenderer.on('nativeModuleCallback', (e, msg) => NativeModules.hostCallback(msg));
|
||||
ipcRenderer.on('nativeModuleHostError', (e, err) => NativeModules.hostError(err));
|
||||
ipcRenderer.on('nativeModuleHostExit', (e, { code, sig }) => NativeModules.hostExit(code, sig));
|
||||
ipcRenderer.on('nativeModuleHostDisconnect', () => NativeModules.hostDisconnect());
|
||||
|
||||
const handlers = {
|
||||
yubikeys(numYubiKeys) {
|
||||
Events.emit('native-modules-yubikeys', { numYubiKeys });
|
||||
|
@ -50,37 +57,39 @@ if (Launcher) {
|
|||
|
||||
NativeModules = {
|
||||
startHost() {
|
||||
if (host) {
|
||||
return;
|
||||
if (hostRunning) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (hostStartPromise) {
|
||||
return hostStartPromise;
|
||||
}
|
||||
|
||||
logger.debug('Starting native module host');
|
||||
|
||||
const path = Launcher.req('path');
|
||||
const appContentRoot = Launcher.remoteApp().getAppContentRoot();
|
||||
const mainModulePath = path.join(appContentRoot, 'native-module-host.js');
|
||||
hostStartPromise = this.callNoWait('start').then(() => {
|
||||
hostStartPromise = undefined;
|
||||
hostRunning = true;
|
||||
|
||||
const { fork } = Launcher.req('child_process');
|
||||
if (this.usbListenerRunning) {
|
||||
return this.call('startUsbListener');
|
||||
}
|
||||
});
|
||||
|
||||
host = fork(mainModulePath);
|
||||
|
||||
host.on('message', (message) => this.hostCallback(message));
|
||||
|
||||
host.on('error', (e) => this.hostError(e));
|
||||
host.on('exit', (code, sig) => this.hostExit(code, sig));
|
||||
|
||||
if (this.usbListenerRunning) {
|
||||
this.call('start-usb');
|
||||
}
|
||||
return hostStartPromise;
|
||||
},
|
||||
|
||||
hostError(e) {
|
||||
logger.error('Host error', e);
|
||||
},
|
||||
|
||||
hostDisconnect() {
|
||||
logger.error('Host disconnected');
|
||||
},
|
||||
|
||||
hostExit(code, sig) {
|
||||
logger.error(`Host exited with code ${code} and signal ${sig}`);
|
||||
host = null;
|
||||
|
||||
hostRunning = false;
|
||||
|
||||
const err = new Error('Native module host crashed');
|
||||
|
||||
|
@ -120,22 +129,19 @@ if (Launcher) {
|
|||
},
|
||||
|
||||
call(cmd, ...args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!host) {
|
||||
try {
|
||||
this.startHost();
|
||||
} catch (e) {
|
||||
return reject(e);
|
||||
}
|
||||
}
|
||||
return this.startHost().then(() => this.callNoWait(cmd, ...args));
|
||||
},
|
||||
|
||||
callNoWait(cmd, ...args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
callId++;
|
||||
if (callId === Number.MAX_SAFE_INTEGER) {
|
||||
callId = 1;
|
||||
}
|
||||
// logger.debug('Call', cmd, args, callId);
|
||||
promises[callId] = { cmd, resolve, reject };
|
||||
host.send({ cmd, args, callId });
|
||||
|
||||
ipcRenderer.send('nativeModuleCall', { cmd, args, callId });
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -146,7 +152,7 @@ if (Launcher) {
|
|||
|
||||
stopUsbListener() {
|
||||
this.usbListenerRunning = false;
|
||||
if (host) {
|
||||
if (hostRunning) {
|
||||
this.call('stopUsbListener');
|
||||
}
|
||||
},
|
||||
|
@ -161,7 +167,7 @@ if (Launcher) {
|
|||
},
|
||||
|
||||
yubiKeyCancelChallengeResponse() {
|
||||
if (host) {
|
||||
if (hostRunning) {
|
||||
this.call('yubiKeyCancelChallengeResponse');
|
||||
}
|
||||
},
|
||||
|
@ -171,13 +177,11 @@ if (Launcher) {
|
|||
},
|
||||
|
||||
hardwareEncrypt: async (value) => {
|
||||
const { ipcRenderer } = Launcher.electron();
|
||||
const { data, salt } = await ipcRenderer.invoke('hardwareEncrypt', value.dataAndSalt());
|
||||
return new kdbxweb.ProtectedValue(data, salt);
|
||||
},
|
||||
|
||||
hardwareDecrypt: async (value, touchIdPrompt) => {
|
||||
const { ipcRenderer } = Launcher.electron();
|
||||
const { data, salt } = await ipcRenderer.invoke(
|
||||
'hardwareDecrypt',
|
||||
value.dataAndSalt(),
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
let perfTimestamps = [{ name: 'pre-init', ts: process.hrtime() }];
|
||||
|
||||
if (process.send && process.argv.includes('--native-module-host')) {
|
||||
require('./native-module-host');
|
||||
return;
|
||||
}
|
||||
|
||||
const electron = require('electron');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
|
|
@ -6,9 +6,13 @@ const attachedYubiKeys = [];
|
|||
let usbListenerRunning = false;
|
||||
let autoType;
|
||||
|
||||
process.on('disconnect', () => process.exit(0));
|
||||
|
||||
startListener();
|
||||
|
||||
const messageHandlers = {
|
||||
start() {},
|
||||
|
||||
startUsbListener() {
|
||||
if (usbListenerRunning) {
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
const path = require('path');
|
||||
const { spawn } = require('child_process');
|
||||
|
||||
let callbackWebContents;
|
||||
let nativeModuleHost;
|
||||
|
||||
function startHost() {
|
||||
const exeName = path.basename(process.execPath, '.exe');
|
||||
const args = ['--native-module-host', '--in-process-gpu', '--disable-gpu'];
|
||||
if (exeName === 'Electron') {
|
||||
args.unshift(path.join(process.mainModule.path, 'main.js'));
|
||||
}
|
||||
|
||||
nativeModuleHost = spawn(process.helperExecPath, args, {
|
||||
env: process.env,
|
||||
cwd: process.cwd(),
|
||||
stdio: ['inherit', 'inherit', 'inherit', 'ipc']
|
||||
});
|
||||
|
||||
nativeModuleHost.on('message', onHostMessage);
|
||||
nativeModuleHost.on('error', onHostError);
|
||||
nativeModuleHost.on('exit', onHostExit);
|
||||
nativeModuleHost.on('disconnect', onHostDisconnect);
|
||||
}
|
||||
|
||||
function nativeModuleCall(event, msg) {
|
||||
callbackWebContents = event.sender;
|
||||
if (!nativeModuleHost) {
|
||||
startHost();
|
||||
}
|
||||
if (nativeModuleHost) {
|
||||
nativeModuleHost.send(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function onHostMessage(msg) {
|
||||
callback('nativeModuleCallback', msg);
|
||||
}
|
||||
|
||||
function onHostError(e) {
|
||||
callback('nativeModuleHostError', e);
|
||||
}
|
||||
|
||||
function onHostExit(code, sig) {
|
||||
nativeModuleHost = undefined;
|
||||
callback('nativeModuleHostExit', { code, sig });
|
||||
}
|
||||
|
||||
function onHostDisconnect() {
|
||||
nativeModuleHost = undefined;
|
||||
callback('nativeModuleHostDisconnect');
|
||||
}
|
||||
|
||||
function callback(name, arg) {
|
||||
try {
|
||||
callbackWebContents.send(name, arg);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
module.exports = { nativeModuleCall };
|
|
@ -1,7 +1,9 @@
|
|||
const { ipcMain } = require('electron');
|
||||
const { hardwareEncrypt, hardwareDecrypt } = require('./ipc-handlers/hardware-crypto');
|
||||
const { nativeModuleCall } = require('./ipc-handlers/native-module-host-proxy');
|
||||
|
||||
module.exports.setupIpcHandlers = () => {
|
||||
ipcMain.handle('hardwareEncrypt', hardwareEncrypt);
|
||||
ipcMain.handle('hardwareDecrypt', hardwareDecrypt);
|
||||
ipcMain.on('nativeModuleCall', nativeModuleCall);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue