fixed native module helper

This commit is contained in:
antelle 2021-02-08 22:49:53 +01:00
parent 5af7837468
commit ec7155809b
No known key found for this signature in database
GPG Key ID: 63C9777AAB7C563C
5 changed files with 106 additions and 31 deletions

View File

@ -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(),

View File

@ -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');

View File

@ -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;

View File

@ -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 };

View File

@ -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);
};