reworked unlocking files for auto-type and browser extension connection

fix #1768
This commit is contained in:
antelle 2021-04-26 11:20:20 +02:00
parent 29e5c14009
commit 8fc6f49fb4
No known key found for this signature in database
GPG Key ID: 63C9777AAB7C563C
4 changed files with 66 additions and 57 deletions

View File

@ -20,7 +20,6 @@ const AutoType = {
enabled: !!(Launcher && Launcher.autoTypeSupported),
supportsEventsWithWindowId: !!(Launcher && Launcher.platform() === 'linux'),
selectEntryView: false,
pendingEvent: null,
running: false,
init() {
@ -28,10 +27,6 @@ const AutoType = {
return;
}
Events.on('auto-type', (e) => this.handleEvent(e));
Events.on('main-window-blur', (e) => this.mainWindowBlur(e));
Events.on('main-window-focus', (e) => this.mainWindowFocus(e));
Events.on('main-window-will-close', (e) => this.mainWindowWillClose(e));
Events.on('closed-open-view', (e) => this.processPendingEvent(e));
},
handleEvent(e) {
@ -216,16 +211,24 @@ const AutoType = {
},
selectEntryAndRun() {
this.getActiveWindowInfo((e, windowInfo) => {
this.getActiveWindowInfo(async (e, windowInfo) => {
const filter = new AutoTypeFilter(windowInfo, AppModel.instance);
const evt = { filter, windowInfo };
if (!AppModel.instance.files.hasOpenFiles()) {
this.pendingEvent = evt;
logger.debug('auto-type event delayed');
this.focusMainWindow();
} else {
this.processEventWithFilter(evt);
try {
await AppModel.instance.unlockAnyFile();
} catch {
logger.debug('auto-type event canceled');
return;
}
if (this.selectEntryView) {
this.selectEntryView.show();
}
}
logger.debug('processing auto-type event');
this.processEventWithFilter(evt);
});
},
@ -264,51 +267,6 @@ const AutoType = {
this.selectEntryView.hide();
Events.emit('open-file');
});
},
mainWindowBlur() {
this.mainWindowBlurTimer = setTimeout(() => {
// macOS emits focus-blur-focus event in a row when triggering auto-type from minimized state
delete this.mainWindowBlurTimer;
this.resetPendingEvent();
if (this.selectEntryView) {
this.selectEntryView.emit('result', undefined);
}
}, Timeouts.AutoTypeWindowFocusAfterBlur);
},
mainWindowFocus() {
if (this.mainWindowBlurTimer) {
clearTimeout(this.mainWindowBlurTimer);
this.mainWindowBlurTimer = null;
}
},
mainWindowWillClose() {
this.resetPendingEvent();
if (this.selectEntryView) {
this.selectEntryView.emit('result', undefined);
}
},
resetPendingEvent() {
if (this.pendingEvent) {
this.pendingEvent = null;
logger.debug('auto-type event canceled');
}
},
processPendingEvent() {
if (this.selectEntryView) {
this.selectEntryView.show();
}
if (!this.pendingEvent) {
return;
}
logger.debug('processing pending auto-type event');
const evt = this.pendingEvent;
this.pendingEvent = null;
this.processEventWithFilter(evt);
}
};

View File

@ -17,6 +17,7 @@ import { MenuModel } from 'models/menu/menu-model';
import { PluginManager } from 'plugins/plugin-manager';
import { Features } from 'util/features';
import { DateFormat } from 'comp/i18n/date-format';
import { Launcher } from 'comp/launcher';
import { UrlFormat } from 'util/formatting/url-format';
import { IdGenerator } from 'util/generators/id-generator';
import { Locale } from 'util/locale';
@ -38,6 +39,8 @@ class AppModel {
advancedSearch = null;
attachedYubiKeysCount = 0;
memoryPasswordStorage = {};
fileUnlockPromise = null;
hardwareDecryptInProgress = false;
constructor() {
Events.on('refresh', this.refresh.bind(this));
@ -48,6 +51,9 @@ class AppModel {
Events.on('select-entry', this.selectEntry.bind(this));
Events.on('unset-keyfile', this.unsetKeyFile.bind(this));
Events.on('usb-devices-changed', this.usbDevicesChanged.bind(this));
Events.on('main-window-blur', this.mainWindowBlur.bind(this));
Events.on('hardware-decrypt-started', this.hardwareDecryptStarted.bind(this));
Events.on('hardware-decrypt-finished', this.hardwareDecryptFinished.bind(this));
this.appLogger = new Logger('app');
AppModel.instance = this;
@ -167,11 +173,21 @@ class AppModel {
page: 'file',
file
});
this.refresh();
file.on('reload', this.reloadFile.bind(this));
file.on('change', () => Events.emit('file-changed', file));
file.on('ejected', () => this.closeFile(file));
Events.emit('file-opened');
if (this.fileUnlockPromise) {
this.appLogger.info('Running pending file unlock operation');
this.fileUnlockPromise.resolve(file);
this.fileUnlockPromise = null;
}
return true;
}
@ -1414,6 +1430,39 @@ class AppModel {
this.memoryPasswordStorage = {};
}
}
unlockAnyFile() {
this.rejectPendingFileUnlockPromise('Replaced with a new operation');
return new Promise((resolve, reject) => {
this.fileUnlockPromise = { resolve, reject };
this.appLogger.info('Pending file unlock operation is set');
});
}
rejectPendingFileUnlockPromise(reason) {
if (this.fileUnlockPromise) {
this.appLogger.info('Cancel pending file unlock operation', reason);
this.fileUnlockPromise.reject(new Error(reason));
this.fileUnlockPromise = null;
}
}
mainWindowBlur() {
if (!this.hardwareDecryptInProgress) {
this.rejectPendingFileUnlockPromise('Main window blur');
}
}
hardwareDecryptStarted() {
this.hardwareDecryptInProgress = true;
}
hardwareDecryptFinished() {
this.hardwareDecryptInProgress = false;
if (!Launcher.isAppFocused()) {
this.rejectPendingFileUnlockPromise('App is not focused after hardware decrypt');
}
}
}
export { AppModel };

View File

@ -171,9 +171,6 @@ class AppView extends View {
this.views.open.on('close', () => {
this.showEntries();
});
this.views.open.on('remove', () => {
Events.emit('closed-open-view');
});
}
showLastOpenFile() {

View File

@ -680,13 +680,18 @@ class OpenView extends View {
const encryptedPassword = kdbxweb.ProtectedValue.fromBase64(
this.encryptedPassword.value
);
Events.emit('hardware-decrypt-started');
NativeModules.hardwareDecrypt(encryptedPassword, touchIdPrompt)
.then((password) => {
Events.emit('hardware-decrypt-finished');
this.params.password = password;
this.params.encryptedPassword = this.encryptedPassword;
this.model.openFile(this.params, (err) => this.openDbComplete(err));
})
.catch((err) => {
Events.emit('hardware-decrypt-finished');
if (err.message.includes('User refused')) {
err.userCanceled = true;
} else if (err.message.includes('SecKeyCreateDecryptedData')) {