mirror of
https://github.com/bitwarden/jslib
synced 2025-12-21 02:33:37 +00:00
Merge commit '8b2dfc6cdcb8ff5b604364c2ea6d343473aee7cd' into feature/workspaces
# Conflicts: # common/spec/importers/fsecureFskImporter.spec.ts # common/spec/services/cipher.service.spec.ts # package-lock.json # package.json
This commit is contained in:
89
electron/package-lock.json
generated
89
electron/package-lock.json
generated
@@ -11,20 +11,21 @@
|
||||
"dependencies": {
|
||||
"@bitwarden/jslib-common": "file:../common",
|
||||
"@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4",
|
||||
"electron": "14.2.0",
|
||||
"electron": "16.0.2",
|
||||
"electron-log": "4.4.1",
|
||||
"electron-store": "8.0.1",
|
||||
"electron-updater": "4.3.9",
|
||||
"electron-updater": "4.6.1",
|
||||
"forcefocus": "^1.1.0",
|
||||
"keytar": "7.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.17.1",
|
||||
"@types/node": "^16.11.12",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "4.3.5"
|
||||
}
|
||||
},
|
||||
"../common": {
|
||||
"name": "@bitwarden/jslib-common",
|
||||
"version": "0.0.0",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
@@ -41,7 +42,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lunr": "^2.3.3",
|
||||
"@types/node": "^14.17.1",
|
||||
"@types/node": "^16.11.12",
|
||||
"@types/node-forge": "^0.9.7",
|
||||
"@types/papaparse": "^5.2.5",
|
||||
"@types/tldjs": "^2.3.0",
|
||||
@@ -104,9 +105,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "14.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.0.tgz",
|
||||
"integrity": "sha512-0GeIl2kmVMXEnx8tg1SlG6Gg8vkqirrW752KqolYo1PHevhhZN3bhJ67qHj+bQaINhX0Ra3TlWwRvMCd9iEfNQ=="
|
||||
"version": "16.11.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz",
|
||||
"integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.3.9",
|
||||
@@ -288,9 +290,9 @@
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
|
||||
},
|
||||
"node_modules/builder-util-runtime": {
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.7.5.tgz",
|
||||
"integrity": "sha512-fgUFHKtMNjdvH6PDRFntdIGUPgwZ69sXsAqEulCtoiqgWes5agrMq/Ud274zjJRTbckYh2PHh8/1CpFc6dpsbQ==",
|
||||
"version": "8.9.1",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.9.1.tgz",
|
||||
"integrity": "sha512-c8a8J3wK6BIVLW7ls+7TRK9igspTbzWmUqxFbgK0m40Ggm6efUbxtWVCGIjc+dtchyr5qAMAUL6iEGRdS/6vwg==",
|
||||
"dependencies": {
|
||||
"debug": "^4.3.2",
|
||||
"sax": "^1.2.4"
|
||||
@@ -544,12 +546,12 @@
|
||||
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "14.2.0",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-14.2.0.tgz",
|
||||
"integrity": "sha512-6CmAv1P0xcwK3FQOSA27fHI36/wctSFVgj46VODn56srXXQWeolkK1VzeAFNE613iAuuH9jJdHvE3gz+c7XkNA==",
|
||||
"version": "16.0.2",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-16.0.2.tgz",
|
||||
"integrity": "sha512-kT746yVMztrP4BbT3nrFNcUcfgFu2yelUw6TWBVTy0pju+fBISaqcvoiMrq+8U0vRpoXSu2MJYygOf4T0Det7g==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@electron/get": "^1.0.1",
|
||||
"@electron/get": "^1.13.0",
|
||||
"@types/node": "^14.6.2",
|
||||
"extract-zip": "^1.0.3"
|
||||
},
|
||||
@@ -578,15 +580,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron-updater": {
|
||||
"version": "4.3.9",
|
||||
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-4.3.9.tgz",
|
||||
"integrity": "sha512-LCNfedSwZfS4Hza+pDyPR05LqHtGorCStaBgVpRnfKxOlZcvpYEX0AbMeH5XUtbtGRoH2V8osbbf2qKPNb7AsA==",
|
||||
"version": "4.6.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-4.6.1.tgz",
|
||||
"integrity": "sha512-YsU1mHqXLrXXmBMsxhxy24PrbaB8rnpZDPmFa2gOkTYk/Ch13+R0fjsRSpPYvqtskVVY0ux8fu+HnUkVkqc7og==",
|
||||
"dependencies": {
|
||||
"@types/semver": "^7.3.5",
|
||||
"builder-util-runtime": "8.7.5",
|
||||
"@types/semver": "^7.3.6",
|
||||
"builder-util-runtime": "8.9.1",
|
||||
"fs-extra": "^10.0.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lazy-val": "^1.0.4",
|
||||
"lazy-val": "^1.0.5",
|
||||
"lodash.escaperegexp": "^4.1.2",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"semver": "^7.3.5"
|
||||
@@ -638,6 +640,11 @@
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron/node_modules/@types/node": {
|
||||
"version": "14.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.0.tgz",
|
||||
"integrity": "sha512-0GeIl2kmVMXEnx8tg1SlG6Gg8vkqirrW752KqolYo1PHevhhZN3bhJ67qHj+bQaINhX0Ra3TlWwRvMCd9iEfNQ=="
|
||||
},
|
||||
"node_modules/encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
@@ -1887,7 +1894,7 @@
|
||||
"@microsoft/signalr": "5.0.10",
|
||||
"@microsoft/signalr-protocol-msgpack": "5.0.10",
|
||||
"@types/lunr": "^2.3.3",
|
||||
"@types/node": "^14.17.1",
|
||||
"@types/node": "^16.11.12",
|
||||
"@types/node-forge": "^0.9.7",
|
||||
"@types/papaparse": "^5.2.5",
|
||||
"@types/tldjs": "^2.3.0",
|
||||
@@ -1942,9 +1949,10 @@
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "14.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.0.tgz",
|
||||
"integrity": "sha512-0GeIl2kmVMXEnx8tg1SlG6Gg8vkqirrW752KqolYo1PHevhhZN3bhJ67qHj+bQaINhX0Ra3TlWwRvMCd9iEfNQ=="
|
||||
"version": "16.11.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz",
|
||||
"integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/semver": {
|
||||
"version": "7.3.9",
|
||||
@@ -2076,9 +2084,9 @@
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
|
||||
},
|
||||
"builder-util-runtime": {
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.7.5.tgz",
|
||||
"integrity": "sha512-fgUFHKtMNjdvH6PDRFntdIGUPgwZ69sXsAqEulCtoiqgWes5agrMq/Ud274zjJRTbckYh2PHh8/1CpFc6dpsbQ==",
|
||||
"version": "8.9.1",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.9.1.tgz",
|
||||
"integrity": "sha512-c8a8J3wK6BIVLW7ls+7TRK9igspTbzWmUqxFbgK0m40Ggm6efUbxtWVCGIjc+dtchyr5qAMAUL6iEGRdS/6vwg==",
|
||||
"requires": {
|
||||
"debug": "^4.3.2",
|
||||
"sax": "^1.2.4"
|
||||
@@ -2268,13 +2276,20 @@
|
||||
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
|
||||
},
|
||||
"electron": {
|
||||
"version": "14.2.0",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-14.2.0.tgz",
|
||||
"integrity": "sha512-6CmAv1P0xcwK3FQOSA27fHI36/wctSFVgj46VODn56srXXQWeolkK1VzeAFNE613iAuuH9jJdHvE3gz+c7XkNA==",
|
||||
"version": "16.0.2",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-16.0.2.tgz",
|
||||
"integrity": "sha512-kT746yVMztrP4BbT3nrFNcUcfgFu2yelUw6TWBVTy0pju+fBISaqcvoiMrq+8U0vRpoXSu2MJYygOf4T0Det7g==",
|
||||
"requires": {
|
||||
"@electron/get": "^1.0.1",
|
||||
"@electron/get": "^1.13.0",
|
||||
"@types/node": "^14.6.2",
|
||||
"extract-zip": "^1.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "14.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.0.tgz",
|
||||
"integrity": "sha512-0GeIl2kmVMXEnx8tg1SlG6Gg8vkqirrW752KqolYo1PHevhhZN3bhJ67qHj+bQaINhX0Ra3TlWwRvMCd9iEfNQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"electron-log": {
|
||||
@@ -2292,15 +2307,15 @@
|
||||
}
|
||||
},
|
||||
"electron-updater": {
|
||||
"version": "4.3.9",
|
||||
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-4.3.9.tgz",
|
||||
"integrity": "sha512-LCNfedSwZfS4Hza+pDyPR05LqHtGorCStaBgVpRnfKxOlZcvpYEX0AbMeH5XUtbtGRoH2V8osbbf2qKPNb7AsA==",
|
||||
"version": "4.6.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-4.6.1.tgz",
|
||||
"integrity": "sha512-YsU1mHqXLrXXmBMsxhxy24PrbaB8rnpZDPmFa2gOkTYk/Ch13+R0fjsRSpPYvqtskVVY0ux8fu+HnUkVkqc7og==",
|
||||
"requires": {
|
||||
"@types/semver": "^7.3.5",
|
||||
"builder-util-runtime": "8.7.5",
|
||||
"@types/semver": "^7.3.6",
|
||||
"builder-util-runtime": "8.9.1",
|
||||
"fs-extra": "^10.0.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lazy-val": "^1.0.4",
|
||||
"lazy-val": "^1.0.5",
|
||||
"lodash.escaperegexp": "^4.1.2",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"semver": "^7.3.5"
|
||||
|
||||
@@ -22,17 +22,17 @@
|
||||
"test:node": " "
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.17.1",
|
||||
"@types/node": "^16.11.12",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "4.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bitwarden/jslib-common": "file:../common",
|
||||
"@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4",
|
||||
"electron": "14.2.0",
|
||||
"electron": "16.0.2",
|
||||
"electron-log": "4.4.1",
|
||||
"electron-store": "8.0.1",
|
||||
"electron-updater": "4.3.9",
|
||||
"electron-updater": "4.6.1",
|
||||
"forcefocus": "^1.1.0",
|
||||
"keytar": "7.7.0"
|
||||
}
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
import { ipcMain, systemPreferences } from 'electron';
|
||||
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
|
||||
import { BiometricMain } from 'jslib-common/abstractions/biometric.main';
|
||||
import { ElectronConstants } from './electronConstants';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
|
||||
export default class BiometricDarwinMain implements BiometricMain {
|
||||
isError: boolean = false;
|
||||
|
||||
constructor(private storageService: StorageService, private i18nservice: I18nService) {}
|
||||
constructor(private i18nservice: I18nService, private stateService: StateService) {}
|
||||
|
||||
async init() {
|
||||
this.storageService.save(ElectronConstants.enableBiometric, await this.supportsBiometric());
|
||||
this.storageService.save(ConstantsService.biometricText, 'unlockWithTouchId');
|
||||
this.storageService.save(ElectronConstants.noAutoPromptBiometricsText, 'noAutoPromptTouchId');
|
||||
await this.stateService.setEnableBiometric(await this.supportsBiometric());
|
||||
await this.stateService.setBiometricText('unlockWithTouchId');
|
||||
await this.stateService.setNoAutoPromptBiometricsText('noAutoPromptTouchId');
|
||||
|
||||
ipcMain.on('biometric', async (event: any, message: any) => {
|
||||
event.returnValue = await this.authenticateBiometric();
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import { ipcMain } from 'electron';
|
||||
import forceFocus from 'forcefocus';
|
||||
|
||||
import { ElectronConstants } from './electronConstants';
|
||||
import { WindowMain } from './window.main';
|
||||
|
||||
import { BiometricMain } from 'jslib-common/abstractions/biometric.main';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
|
||||
export default class BiometricWindowsMain implements BiometricMain {
|
||||
isError: boolean = false;
|
||||
|
||||
private windowsSecurityCredentialsUiModule: any;
|
||||
|
||||
constructor(private storageService: StorageService, private i18nservice: I18nService, private windowMain: WindowMain,
|
||||
private logService: LogService) { }
|
||||
constructor(private i18nservice: I18nService, private windowMain: WindowMain,
|
||||
private stateService: StateService, private logService: LogService) { }
|
||||
|
||||
async init() {
|
||||
this.windowsSecurityCredentialsUiModule = this.getWindowsSecurityCredentialsUiModule();
|
||||
@@ -27,9 +25,9 @@ export default class BiometricWindowsMain implements BiometricMain {
|
||||
// store error state so we can let the user know on the settings page
|
||||
this.isError = true;
|
||||
}
|
||||
this.storageService.save(ElectronConstants.enableBiometric, supportsBiometric);
|
||||
this.storageService.save(ConstantsService.biometricText, 'unlockWithWindowsHello');
|
||||
this.storageService.save(ElectronConstants.noAutoPromptBiometricsText, 'noAutoPromptWindowsHello');
|
||||
await this.stateService.setEnableBiometric(supportsBiometric);
|
||||
await this.stateService.setBiometricText('unlockWithWindowsHello');
|
||||
await this.stateService.setNoAutoPromptBiometricsText('noAutoPromptWindowsHello');
|
||||
|
||||
ipcMain.on('biometric', async (event: any, message: any) => {
|
||||
event.returnValue = await this.authenticateBiometric();
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
export class ElectronConstants {
|
||||
static readonly enableMinimizeToTrayKey: string = 'enableMinimizeToTray';
|
||||
static readonly enableCloseToTrayKey: string = 'enableCloseToTray';
|
||||
static readonly enableTrayKey: string = 'enableTray';
|
||||
static readonly enableStartToTrayKey: string = 'enableStartToTrayKey';
|
||||
static readonly enableAlwaysOnTopKey: string = 'enableAlwaysOnTopKey';
|
||||
static readonly minimizeOnCopyToClipboardKey: string = 'minimizeOnCopyToClipboardKey';
|
||||
static readonly enableBiometric: string = 'enabledBiometric';
|
||||
static readonly enableBrowserIntegration: string = 'enableBrowserIntegration';
|
||||
static readonly enableBrowserIntegrationFingerprint: string = 'enableBrowserIntegrationFingerprint';
|
||||
static readonly alwaysShowDock: string = 'alwaysShowDock';
|
||||
static readonly openAtLogin: string = 'openAtLogin';
|
||||
static readonly noAutoPromptBiometricsText: string = 'noAutoPromptBiometricsText';
|
||||
}
|
||||
@@ -1,16 +1,19 @@
|
||||
import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { KeySuffixOptions, StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
|
||||
import { CryptoService } from 'jslib-common/services/crypto.service';
|
||||
|
||||
import { KeySuffixOptions } from 'jslib-common/enums/keySuffixOptions';
|
||||
import { StorageLocation } from 'jslib-common/enums/storageLocation';
|
||||
import { SymmetricCryptoKey } from 'jslib-common/models/domain/symmetricCryptoKey';
|
||||
import { CryptoService, Keys } from 'jslib-common/services/crypto.service';
|
||||
|
||||
export class ElectronCryptoService extends CryptoService {
|
||||
|
||||
constructor(storageService: StorageService, secureStorageService: StorageService,
|
||||
cryptoFunctionService: CryptoFunctionService, platformUtilService: PlatformUtilsService,
|
||||
logService: LogService) {
|
||||
super(storageService, secureStorageService, cryptoFunctionService, platformUtilService, logService);
|
||||
constructor(cryptoFunctionService: CryptoFunctionService, platformUtilService: PlatformUtilsService,
|
||||
logService: LogService, stateService: StateService) {
|
||||
super(cryptoFunctionService, platformUtilService, logService, stateService);
|
||||
}
|
||||
|
||||
async hasKeyStored(keySuffix: KeySuffixOptions): Promise<boolean> {
|
||||
@@ -18,17 +21,17 @@ export class ElectronCryptoService extends CryptoService {
|
||||
return super.hasKeyStored(keySuffix);
|
||||
}
|
||||
|
||||
protected async storeKey(key: SymmetricCryptoKey) {
|
||||
if (await this.shouldStoreKey('auto')) {
|
||||
await this.secureStorageService.save(Keys.key, key.keyB64, { keySuffix: 'auto' });
|
||||
protected async storeKey(key: SymmetricCryptoKey, userId?: string) {
|
||||
if (await this.shouldStoreKey(KeySuffixOptions.Auto, userId)) {
|
||||
await this.stateService.setCryptoMasterKeyAuto(key.keyB64, { userId: userId });
|
||||
} else {
|
||||
this.clearStoredKey('auto');
|
||||
this.clearStoredKey(KeySuffixOptions.Auto);
|
||||
}
|
||||
|
||||
if (await this.shouldStoreKey('biometric')) {
|
||||
await this.secureStorageService.save(Keys.key, key.keyB64, { keySuffix: 'biometric' });
|
||||
if (await this.shouldStoreKey(KeySuffixOptions.Biometric, userId)) {
|
||||
await this.stateService.setCryptoMasterKeyBiometric(key.keyB64, { userId: userId });
|
||||
} else {
|
||||
this.clearStoredKey('biometric');
|
||||
this.clearStoredKey(KeySuffixOptions.Biometric);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,24 +46,24 @@ export class ElectronCryptoService extends CryptoService {
|
||||
*/
|
||||
private async upgradeSecurelyStoredKey() {
|
||||
// attempt key upgrade, but if we fail just delete it. Keys will be stored property upon unlock anyway.
|
||||
const key = await this.secureStorageService.get<string>(Keys.key);
|
||||
const key = await this.stateService.getCryptoMasterKeyB64();
|
||||
|
||||
if (key == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (await this.shouldStoreKey('auto')) {
|
||||
await this.secureStorageService.save(Keys.key, key, { keySuffix: 'auto' });
|
||||
if (await this.shouldStoreKey(KeySuffixOptions.Auto)) {
|
||||
await this.stateService.setCryptoMasterKeyAuto(key);
|
||||
}
|
||||
if (await this.shouldStoreKey('biometric')) {
|
||||
await this.secureStorageService.save(Keys.key, key, { keySuffix: 'biometric' });
|
||||
if (await this.shouldStoreKey(KeySuffixOptions.Biometric)) {
|
||||
await this.stateService.setCryptoMasterKeyBiometric(key);
|
||||
}
|
||||
} catch (e) {
|
||||
this.logService.error(`Encountered error while upgrading obsolete Bitwarden secure storage item:`);
|
||||
this.logService.error(e);
|
||||
}
|
||||
|
||||
await this.secureStorageService.remove(Keys.key);
|
||||
await this.stateService.setCryptoMasterKeyB64(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,7 @@ import { ThemeType } from 'jslib-common/enums/themeType';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
|
||||
import { ElectronConstants } from '../electronConstants';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
|
||||
export class ElectronPlatformUtilsService implements PlatformUtilsService {
|
||||
identityClientId: string;
|
||||
@@ -27,7 +23,7 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService {
|
||||
private deviceCache: DeviceType = null;
|
||||
|
||||
constructor(protected i18nService: I18nService, private messagingService: MessagingService,
|
||||
private isDesktopApp: boolean, private storageService: StorageService) {
|
||||
private isDesktopApp: boolean, private stateService: StateService) {
|
||||
this.identityClientId = isDesktopApp ? 'desktop' : 'connector';
|
||||
}
|
||||
|
||||
@@ -178,8 +174,8 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService {
|
||||
return Promise.resolve(clipboard.readText(type));
|
||||
}
|
||||
|
||||
supportsBiometric(): Promise<boolean> {
|
||||
return this.storageService.get(ElectronConstants.enableBiometric);
|
||||
async supportsBiometric(): Promise<boolean> {
|
||||
return await this.stateService.getEnableBiometric();
|
||||
}
|
||||
|
||||
authenticateBiometric(): Promise<boolean> {
|
||||
@@ -200,7 +196,7 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService {
|
||||
}
|
||||
|
||||
async getEffectiveTheme() {
|
||||
const theme = await this.storageService.get<ThemeType>(ConstantsService.themeKey);
|
||||
const theme = await this.stateService.getTheme();
|
||||
if (theme == null || theme === ThemeType.System) {
|
||||
return this.getDefaultSystemTheme();
|
||||
} else {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { ipcRenderer } from 'electron';
|
||||
|
||||
import { StorageService, StorageServiceOptions } from 'jslib-common/abstractions/storage.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
|
||||
import { StorageOptions } from 'jslib-common/models/domain/storageOptions';
|
||||
|
||||
export class ElectronRendererSecureStorageService implements StorageService {
|
||||
async get<T>(key: string, options?: StorageServiceOptions): Promise<T> {
|
||||
async get<T>(key: string, options?: StorageOptions): Promise<T> {
|
||||
const val = ipcRenderer.sendSync('keytar', {
|
||||
action: 'getPassword',
|
||||
key: key,
|
||||
@@ -12,7 +14,7 @@ export class ElectronRendererSecureStorageService implements StorageService {
|
||||
return Promise.resolve(val != null ? JSON.parse(val) as T : null);
|
||||
}
|
||||
|
||||
async has(key: string, options?: StorageServiceOptions): Promise<boolean> {
|
||||
async has(key: string, options?: StorageOptions): Promise<boolean> {
|
||||
const val = ipcRenderer.sendSync('keytar', {
|
||||
action: 'hasPassword',
|
||||
key: key,
|
||||
@@ -21,7 +23,7 @@ export class ElectronRendererSecureStorageService implements StorageService {
|
||||
return Promise.resolve(!!val);
|
||||
}
|
||||
|
||||
async save(key: string, obj: any, options?: StorageServiceOptions): Promise<any> {
|
||||
async save(key: string, obj: any, options?: StorageOptions): Promise<any> {
|
||||
ipcRenderer.sendSync('keytar', {
|
||||
action: 'setPassword',
|
||||
key: key,
|
||||
@@ -31,7 +33,7 @@ export class ElectronRendererSecureStorageService implements StorageService {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
async remove(key: string, options?: StorageServiceOptions): Promise<any> {
|
||||
async remove(key: string, options?: StorageOptions): Promise<any> {
|
||||
ipcRenderer.sendSync('keytar', {
|
||||
action: 'deletePassword',
|
||||
key: key,
|
||||
|
||||
@@ -2,7 +2,6 @@ import {
|
||||
app,
|
||||
BrowserWindow,
|
||||
Menu,
|
||||
MenuItem,
|
||||
MenuItemConstructorOptions,
|
||||
nativeImage,
|
||||
Tray,
|
||||
@@ -10,9 +9,8 @@ import {
|
||||
import * as path from 'path';
|
||||
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
|
||||
import { ElectronConstants } from './electronConstants';
|
||||
import { WindowMain } from './window.main';
|
||||
|
||||
export class TrayMain {
|
||||
@@ -24,7 +22,7 @@ export class TrayMain {
|
||||
private pressedIcon: Electron.NativeImage;
|
||||
|
||||
constructor(private windowMain: WindowMain, private i18nService: I18nService,
|
||||
private storageService: StorageService) {
|
||||
private stateService: StateService) {
|
||||
if (process.platform === 'win32') {
|
||||
this.icon = path.join(__dirname, '/images/icon.ico');
|
||||
} else if (process.platform === 'darwin') {
|
||||
@@ -55,21 +53,21 @@ export class TrayMain {
|
||||
}
|
||||
|
||||
this.contextMenu = Menu.buildFromTemplate(menuItemOptions);
|
||||
if (await this.storageService.get<boolean>(ElectronConstants.enableTrayKey)) {
|
||||
if (await this.stateService.getEnableTray()) {
|
||||
this.showTray();
|
||||
}
|
||||
}
|
||||
|
||||
setupWindowListeners(win: BrowserWindow) {
|
||||
win.on('minimize', async (e: Event) => {
|
||||
if (await this.storageService.get<boolean>(ElectronConstants.enableMinimizeToTrayKey)) {
|
||||
if (await this.stateService.getEnableMinimizeToTray()) {
|
||||
e.preventDefault();
|
||||
this.hideToTray();
|
||||
}
|
||||
});
|
||||
|
||||
win.on('close', async (e: Event) => {
|
||||
if (await this.storageService.get<boolean>(ElectronConstants.enableCloseToTrayKey)) {
|
||||
if (await this.stateService.getEnableCloseToTray()) {
|
||||
if (!this.windowMain.isQuitting) {
|
||||
e.preventDefault();
|
||||
this.hideToTray();
|
||||
@@ -78,7 +76,7 @@ export class TrayMain {
|
||||
});
|
||||
|
||||
win.on('show', async (e: Event) => {
|
||||
const enableTray = await this.storageService.get<boolean>(ElectronConstants.enableTrayKey);
|
||||
const enableTray = await this.stateService.getEnableTray();
|
||||
if (!enableTray) {
|
||||
setTimeout(() => this.removeTray(false), 100);
|
||||
}
|
||||
@@ -103,7 +101,7 @@ export class TrayMain {
|
||||
if (this.windowMain.win != null) {
|
||||
this.windowMain.win.hide();
|
||||
}
|
||||
if (this.isDarwin() && !await this.storageService.get<boolean>(ElectronConstants.alwaysShowDock)) {
|
||||
if (this.isDarwin() && !await this.stateService.getAlwaysShowDock()) {
|
||||
this.hideDock();
|
||||
}
|
||||
}
|
||||
@@ -167,7 +165,7 @@ export class TrayMain {
|
||||
}
|
||||
if (this.windowMain.win.isVisible()) {
|
||||
this.windowMain.win.hide();
|
||||
if (this.isDarwin() && !await this.storageService.get<boolean>(ElectronConstants.alwaysShowDock)) {
|
||||
if (this.isDarwin() && !await this.stateService.getAlwaysShowDock()) {
|
||||
this.hideDock();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -25,8 +25,12 @@ export function isAppImage() {
|
||||
return process.platform === 'linux' && 'APPIMAGE' in process.env;
|
||||
}
|
||||
|
||||
export function isMac() {
|
||||
return process.platform === 'darwin';
|
||||
}
|
||||
|
||||
export function isMacAppStore() {
|
||||
return process.platform === 'darwin' && process.mas && process.mas === true;
|
||||
return isMac() && process.mas && process.mas === true;
|
||||
}
|
||||
|
||||
export function isWindowsStore() {
|
||||
|
||||
@@ -7,9 +7,8 @@ import * as path from 'path';
|
||||
import * as url from 'url';
|
||||
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
|
||||
import { ElectronConstants } from './electronConstants';
|
||||
import {
|
||||
cleanUserAgent,
|
||||
isDev,
|
||||
@@ -17,11 +16,8 @@ import {
|
||||
isSnapStore,
|
||||
} from './utils';
|
||||
|
||||
const mainWindowSizeKey = 'mainWindowSize';
|
||||
const WindowEventHandlingDelay = 100;
|
||||
const Keys = {
|
||||
mainWindowSize: 'mainWindowSize',
|
||||
};
|
||||
|
||||
export class WindowMain {
|
||||
win: BrowserWindow;
|
||||
isQuitting: boolean = false;
|
||||
@@ -30,7 +26,7 @@ export class WindowMain {
|
||||
private windowStates: { [key: string]: any; } = {};
|
||||
private enableAlwaysOnTop: boolean = false;
|
||||
|
||||
constructor(private storageService: StorageService, private logService: LogService,
|
||||
constructor(private stateService: StateService, private logService: LogService,
|
||||
private hideTitleBar = false, private defaultWidth = 950, private defaultHeight = 600,
|
||||
private argvCallback: (argv: string[]) => void = null,
|
||||
private createWindowCallback: (win: BrowserWindow) => void) { }
|
||||
@@ -107,18 +103,18 @@ export class WindowMain {
|
||||
}
|
||||
|
||||
async createWindow(): Promise<void> {
|
||||
this.windowStates[Keys.mainWindowSize] = await this.getWindowState(Keys.mainWindowSize, this.defaultWidth,
|
||||
this.windowStates[mainWindowSizeKey] = await this.getWindowState(mainWindowSizeKey, this.defaultWidth,
|
||||
this.defaultHeight);
|
||||
this.enableAlwaysOnTop = await this.storageService.get<boolean>(ElectronConstants.enableAlwaysOnTopKey);
|
||||
this.enableAlwaysOnTop = await this.stateService.getEnableAlwaysOnTop();
|
||||
|
||||
// Create the browser window.
|
||||
this.win = new BrowserWindow({
|
||||
width: this.windowStates[Keys.mainWindowSize].width,
|
||||
height: this.windowStates[Keys.mainWindowSize].height,
|
||||
width: this.windowStates[mainWindowSizeKey].width,
|
||||
height: this.windowStates[mainWindowSizeKey].height,
|
||||
minWidth: 680,
|
||||
minHeight: 500,
|
||||
x: this.windowStates[Keys.mainWindowSize].x,
|
||||
y: this.windowStates[Keys.mainWindowSize].y,
|
||||
x: this.windowStates[mainWindowSizeKey].x,
|
||||
y: this.windowStates[mainWindowSizeKey].y,
|
||||
title: app.name,
|
||||
icon: process.platform === 'linux' ? path.join(__dirname, '/images/icon.png') : undefined,
|
||||
titleBarStyle: this.hideTitleBar && process.platform === 'darwin' ? 'hiddenInset' : undefined,
|
||||
@@ -132,7 +128,7 @@ export class WindowMain {
|
||||
},
|
||||
});
|
||||
|
||||
if (this.windowStates[Keys.mainWindowSize].isMaximized) {
|
||||
if (this.windowStates[mainWindowSizeKey].isMaximized) {
|
||||
this.win.maximize();
|
||||
}
|
||||
|
||||
@@ -158,7 +154,7 @@ export class WindowMain {
|
||||
|
||||
// Emitted when the window is closed.
|
||||
this.win.on('closed', async () => {
|
||||
await this.updateWindowState(Keys.mainWindowSize, this.win);
|
||||
await this.updateWindowState(mainWindowSizeKey, this.win);
|
||||
|
||||
// Dereference the window object, usually you would store window
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
@@ -167,23 +163,23 @@ export class WindowMain {
|
||||
});
|
||||
|
||||
this.win.on('close', async () => {
|
||||
await this.updateWindowState(Keys.mainWindowSize, this.win);
|
||||
await this.updateWindowState(mainWindowSizeKey, this.win);
|
||||
});
|
||||
|
||||
this.win.on('maximize', async () => {
|
||||
await this.updateWindowState(Keys.mainWindowSize, this.win);
|
||||
await this.updateWindowState(mainWindowSizeKey, this.win);
|
||||
});
|
||||
|
||||
this.win.on('unmaximize', async () => {
|
||||
await this.updateWindowState(Keys.mainWindowSize, this.win);
|
||||
await this.updateWindowState(mainWindowSizeKey, this.win);
|
||||
});
|
||||
|
||||
this.win.on('resize', () => {
|
||||
this.windowStateChangeHandler(Keys.mainWindowSize, this.win);
|
||||
this.windowStateChangeHandler(mainWindowSizeKey, this.win);
|
||||
});
|
||||
|
||||
this.win.on('move', () => {
|
||||
this.windowStateChangeHandler(Keys.mainWindowSize, this.win);
|
||||
this.windowStateChangeHandler(mainWindowSizeKey, this.win);
|
||||
});
|
||||
this.win.on('focus', () => {
|
||||
this.win.webContents.send('messagingService', {
|
||||
@@ -200,7 +196,7 @@ export class WindowMain {
|
||||
async toggleAlwaysOnTop() {
|
||||
this.enableAlwaysOnTop = !this.win.isAlwaysOnTop();
|
||||
this.win.setAlwaysOnTop(this.enableAlwaysOnTop);
|
||||
await this.storageService.save(ElectronConstants.enableAlwaysOnTopKey, this.enableAlwaysOnTop);
|
||||
await this.stateService.setEnableAlwaysOnTop(this.enableAlwaysOnTop);
|
||||
}
|
||||
|
||||
private windowStateChangeHandler(configKey: string, win: BrowserWindow) {
|
||||
@@ -219,7 +215,7 @@ export class WindowMain {
|
||||
const bounds = win.getBounds();
|
||||
|
||||
if (this.windowStates[configKey] == null) {
|
||||
this.windowStates[configKey] = await this.storageService.get<any>(configKey);
|
||||
this.windowStates[configKey] = (await this.stateService.getWindow()).get(configKey);
|
||||
if (this.windowStates[configKey] == null) {
|
||||
this.windowStates[configKey] = {};
|
||||
}
|
||||
@@ -235,14 +231,19 @@ export class WindowMain {
|
||||
this.windowStates[configKey].height = bounds.height;
|
||||
}
|
||||
|
||||
await this.storageService.save(configKey, this.windowStates[configKey]);
|
||||
const cachedWindow = await this.stateService.getWindow() ?? new Map<string, any>();
|
||||
cachedWindow.set(configKey, this.windowStates[configKey]);
|
||||
await this.stateService.setWindow(cachedWindow);
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private async getWindowState(configKey: string, defaultWidth: number, defaultHeight: number) {
|
||||
let state = await this.storageService.get<any>(configKey);
|
||||
const windowState = await this.stateService.getWindow() ?? new Map<string, any>();
|
||||
let state = windowState.has(configKey) ?
|
||||
windowState.get(configKey) :
|
||||
null;
|
||||
|
||||
const isValid = state != null && (this.stateHasBounds(state) || state.isMaximized);
|
||||
let displayBounds: Electron.Rectangle = null;
|
||||
|
||||
Reference in New Issue
Block a user