diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index af284dde2b..7e009f0ff9 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -249,7 +249,7 @@ "message": "View" }, "noItemsInList": { - "message": "There are no items to list." + "message": "There are no items to list. :D" }, "itemInformation": { "message": "Item Information" diff --git a/src/background/idle.background.ts b/src/background/idle.background.ts index b5600d8004..1fa725446f 100644 --- a/src/background/idle.background.ts +++ b/src/background/idle.background.ts @@ -1,9 +1,7 @@ -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { NotificationsService } from 'jslib-common/abstractions/notifications.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service'; -import { StorageKey } from 'jslib-common/enums/storageKey'; - const IdleInterval = 60 * 5; // 5 minutes export default class IdleBackground { @@ -11,7 +9,7 @@ export default class IdleBackground { private idleTimer: number = null; private idleState = 'active'; - constructor(private vaultTimeoutService: VaultTimeoutService, private activeAccount: ActiveAccountService, + constructor(private vaultTimeoutService: VaultTimeoutService, private stateService: StateService, private notificationsService: NotificationsService) { this.idle = chrome.idle || (browser != null ? browser.idle : null); } @@ -38,9 +36,9 @@ export default class IdleBackground { if (this.idle.onStateChanged) { this.idle.onStateChanged.addListener(async (newState: string) => { if (newState === 'locked') { // If the screen is locked or the screensaver activates - const timeout = await this.activeAccount.getInformation(StorageKey.VaultTimeout); + const timeout = await this.stateService.getVaultTimeout(); if (timeout === -2) { // On System Lock vault timeout option - const action = await this.activeAccount.getInformation(StorageKey.VaultTimeoutAction); + const action = await this.stateService.getVaultTimeoutAction(); if (action === 'logOut') { await this.vaultTimeoutService.logOut(); } else { diff --git a/src/background/main.background.ts b/src/background/main.background.ts index c36601f8e1..9e83795d54 100644 --- a/src/background/main.background.ts +++ b/src/background/main.background.ts @@ -1,9 +1,6 @@ import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType'; import { CipherType } from 'jslib-common/enums/cipherType'; -import { StorageKey } from 'jslib-common/enums/storageKey'; -import { AccountsManagementService } from 'jslib-common/services/accountsManagement.service'; -import { ActiveAccountService } from 'jslib-common/services/activeAccount.service'; import { ApiService } from 'jslib-common/services/api.service'; import { AppIdService } from 'jslib-common/services/appId.service'; import { AuditService } from 'jslib-common/services/audit.service'; @@ -17,6 +14,7 @@ import { EventService } from 'jslib-common/services/event.service'; import { ExportService } from 'jslib-common/services/export.service'; import { FileUploadService } from 'jslib-common/services/fileUpload.service'; import { FolderService } from 'jslib-common/services/folder.service'; +import { KeyConnectorService } from 'jslib-common/services/keyConnector.service'; import { NotificationsService } from 'jslib-common/services/notifications.service'; import { OrganizationService } from 'jslib-common/services/organization.service'; import { PasswordGenerationService } from 'jslib-common/services/passwordGeneration.service'; @@ -26,15 +24,12 @@ import { SearchService } from 'jslib-common/services/search.service'; import { SendService } from 'jslib-common/services/send.service'; import { SettingsService } from 'jslib-common/services/settings.service'; import { StateService } from 'jslib-common/services/state.service'; -import { StoreService } from 'jslib-common/services/store.service'; import { SyncService } from 'jslib-common/services/sync.service'; import { SystemService } from 'jslib-common/services/system.service'; import { TokenService } from 'jslib-common/services/token.service'; import { TotpService } from 'jslib-common/services/totp.service'; import { WebCryptoFunctionService } from 'jslib-common/services/webCryptoFunction.service'; -import { AccountsManagementService as AccountsManagementServiceAbstraction } from 'jslib-common/abstractions/accountsManagement.service'; -import { ActiveAccountService as ActiveAccountServiceAbstraction } from 'jslib-common/abstractions/activeAccount.service'; import { ApiService as ApiServiceAbstraction } from 'jslib-common/abstractions/api.service'; import { AppIdService as AppIdServiceAbstraction } from 'jslib-common/abstractions/appId.service'; import { AuditService as AuditServiceAbstraction } from 'jslib-common/abstractions/audit.service'; @@ -49,6 +44,7 @@ import { ExportService as ExportServiceAbstraction } from 'jslib-common/abstract import { FileUploadService as FileUploadServiceAbstraction } from 'jslib-common/abstractions/fileUpload.service'; import { FolderService as FolderServiceAbstraction } from 'jslib-common/abstractions/folder.service'; import { I18nService as I18nServiceAbstraction } from 'jslib-common/abstractions/i18n.service'; +import { KeyConnectorService as KeyConnectorServiceAbstraction } from 'jslib-common/abstractions/keyConnector.service'; import { LogService as LogServiceAbstraction } from 'jslib-common/abstractions/log.service'; import { MessagingService as MessagingServiceAbstraction } from 'jslib-common/abstractions/messaging.service'; import { NotificationsService as NotificationsServiceAbstraction } from 'jslib-common/abstractions/notifications.service'; @@ -127,10 +123,9 @@ export default class MainBackground { popupUtilsService: PopupUtilsService; sendService: SendServiceAbstraction; fileUploadService: FileUploadServiceAbstraction; - activeAccount: ActiveAccountServiceAbstraction; - accountsManagementService: AccountsManagementServiceAbstraction; organizationService: OrganizationServiceAbstraction; providerService: ProviderServiceAbstraction; + keyConnectorSerivce: KeyConnectorServiceAbstraction; onUpdatedRan: boolean; onReplacedRan: boolean; @@ -157,10 +152,8 @@ export default class MainBackground { this.messagingService = new BrowserMessagingService(); this.storageService = new BrowserStorageService(); this.secureStorageService = new BrowserStorageService(); - const storeService = new StoreService(this.storageService, this.secureStorageService); - this.accountsManagementService = new AccountsManagementService(this.storageService, this.secureStorageService); - this.activeAccount = new ActiveAccountService(this.accountsManagementService, storeService); - this.platformUtilsService = new BrowserPlatformUtilsService(this.messagingService, this.activeAccount, + // const storeService = new StoreService(this.storageService, this.secureStorageService); + this.platformUtilsService = new BrowserPlatformUtilsService(this.messagingService, this.stateService, (clipboardValue, clearMs) => { if (this.systemService != null) { this.systemService.clearClipboard(clipboardValue, clearMs); @@ -183,30 +176,32 @@ export default class MainBackground { this.cryptoFunctionService = new WebCryptoFunctionService(window, this.platformUtilsService); this.logService = new ConsoleLogService(false); this.cryptoService = new BrowserCryptoService(this.cryptoFunctionService, this.platformUtilsService, - this.logService, this.activeAccount); - this.tokenService = new TokenService(this.activeAccount); + this.logService, this.stateService); + this.tokenService = new TokenService(this.stateService); this.appIdService = new AppIdService(this.storageService); - this.environmentService = new EnvironmentService(this.activeAccount); + this.environmentService = new EnvironmentService(this.stateService); this.apiService = new ApiService(this.tokenService, this.platformUtilsService, this.environmentService, (expired: boolean) => this.logout(expired)); - this.settingsService = new SettingsService(this.activeAccount); + this.settingsService = new SettingsService(this.stateService); this.fileUploadService = new FileUploadService(this.logService, this.apiService); this.cipherService = new CipherService(this.cryptoService, this.settingsService, this.apiService, this.fileUploadService, this.i18nService, () => this.searchService, - this.activeAccount); + this.logService, this.stateService); this.folderService = new FolderService(this.cryptoService, this.apiService, this.i18nService, this.cipherService, - this.activeAccount); + this.stateService); this.collectionService = new CollectionService(this.cryptoService, this.i18nService, - this.activeAccount); + this.stateService); this.searchService = new SearchService(this.cipherService, this.logService, this.i18nService); this.sendService = new SendService(this.cryptoService, this.apiService, this.fileUploadService, this.i18nService, - this.cryptoFunctionService, this.activeAccount); - this.stateService = new StateService(); - this.organizationService = new OrganizationService(this.activeAccount); - this.policyService = new PolicyService(this.activeAccount, this.organizationService); + this.cryptoFunctionService, this.stateService); + this.stateService = new StateService(this.storageService, this.secureStorageService, this.logService); + this.organizationService = new OrganizationService(this.stateService); + this.policyService = new PolicyService(this.stateService, this.organizationService, this.apiService); + this.keyConnectorSerivce = new KeyConnectorService(this.stateService, this.cryptoService, + this.apiService, this.environmentService, this.tokenService, this.logService, this.organizationService); const vaultTimeoutServiceCallbacks = { locked: async () => { @@ -226,23 +221,23 @@ export default class MainBackground { this.collectionService, this.cryptoService, this.platformUtilsService, this.messagingService, this.searchService, this.tokenService, - this.policyService, this.activeAccount, + this.policyService, this.keyConnectorSerivce, this.stateService, vaultTimeoutServiceCallbacks.locked, vaultTimeoutServiceCallbacks.logout); - this.providerService = new ProviderService(this.activeAccount); + this.providerService = new ProviderService(this.stateService); this.syncService = new SyncService(this.apiService, this.settingsService, this.folderService, this.cipherService, this.cryptoService, this.collectionService, this.messagingService, this.policyService, - this.sendService, async (expired: boolean) => await this.logout(expired), - this.activeAccount, this.organizationService, - this.providerService); + this.sendService, this.logService, this.keyConnectorSerivce, + this.stateService, this.organizationService, + this.providerService, async (expired: boolean) => await this.logout(expired)); this.eventService = new EventService(this.apiService, this.cipherService, - this.activeAccount, this.organizationService); + this.stateService, this.logService, this.organizationService); this.passwordGenerationService = new PasswordGenerationService(this.cryptoService, this.policyService, - this.activeAccount); - this.totpService = new TotpService(this.cryptoFunctionService, this.activeAccount); - this.autofillService = new AutofillService(this.cipherService, this.activeAccount, + this.stateService); + this.totpService = new TotpService(this.cryptoFunctionService, this.logService, this.stateService); + this.autofillService = new AutofillService(this.cipherService, this.stateService, this.totpService, this.eventService); this.containerService = new ContainerService(this.cryptoService); this.auditService = new AuditService(this.cryptoFunctionService, this.apiService); @@ -251,7 +246,7 @@ export default class MainBackground { this.notificationsService = new NotificationsService(this.syncService, this.appIdService, this.apiService, this.vaultTimeoutService, this.environmentService, () => this.logout(true), - this.logService, this.activeAccount); + this.logService, this.stateService); this.popupUtilsService = new PopupUtilsService(this.platformUtilsService); const systemUtilsServiceReloadCallback = () => { @@ -260,8 +255,8 @@ export default class MainBackground { BrowserApi.reloadExtension(forceWindowReload ? window : null); return Promise.resolve(); }; - this.systemService = new SystemService(this.vaultTimeoutService, - this.messagingService, this.platformUtilsService, systemUtilsServiceReloadCallback, this.activeAccount); + this.systemService = new SystemService( + this.messagingService, this.platformUtilsService, systemUtilsServiceReloadCallback, this.stateService); // Other fields this.isSafari = this.platformUtilsService.isSafari(); @@ -270,23 +265,22 @@ export default class MainBackground { // Background this.runtimeBackground = new RuntimeBackground(this, this.autofillService, this.cipherService, - this.platformUtilsService as BrowserPlatformUtilsService, this.storageService, + this.platformUtilsService as BrowserPlatformUtilsService, this.i18nService, this.notificationsService, this.systemService, this.vaultTimeoutService, this.environmentService, this.policyService, - this.messagingService, this.folderService); - this.nativeMessagingBackground = new NativeMessagingBackground(this.storageService, this.cryptoService, - this.cryptoFunctionService, this.vaultTimeoutService, - this.runtimeBackground, this.i18nService, - this.messagingService, this.appIdService, - this.platformUtilsService, this.activeAccount); + this.messagingService, this.folderService, this.stateService); + this.nativeMessagingBackground = new NativeMessagingBackground(this.cryptoService, + this.cryptoFunctionService, this.runtimeBackground, + this.i18nService, this.messagingService, this.appIdService, + this.platformUtilsService, this.stateService); this.commandsBackground = new CommandsBackground(this, this.passwordGenerationService, this.platformUtilsService, this.vaultTimeoutService); this.tabsBackground = new TabsBackground(this); this.contextMenusBackground = new ContextMenusBackground(this, this.cipherService, this.passwordGenerationService, this.platformUtilsService, this.vaultTimeoutService, this.eventService, this.totpService); - this.idleBackground = new IdleBackground(this.vaultTimeoutService, this.activeAccount, + this.idleBackground = new IdleBackground(this.vaultTimeoutService, this.stateService, this.notificationsService); this.webRequestBackground = new WebRequestBackground(this.platformUtilsService, this.cipherService, this.vaultTimeoutService); @@ -305,7 +299,7 @@ export default class MainBackground { this.tokenService, this.appIdService, this.i18nService, this.platformUtilsService, backgroundMessagingService, this.vaultTimeoutService, - this.logService, this.activeAccount, this.accountsManagementService); + this.logService, this.cryptoFunctionService, this.keyConnectorSerivce, this.environmentService, this.stateService); } async bootstrap() { @@ -341,7 +335,7 @@ export default class MainBackground { return; } - const isAuthenticated = this.activeAccount.isAuthenticated; + const isAuthenticated = await this.stateService.getIsAuthenticated(); const locked = await this.vaultTimeoutService.isLocked(); let suffix = ''; @@ -360,7 +354,7 @@ export default class MainBackground { return; } - const menuDisabled = await this.storageService.get(StorageKey.DisableContextMenuItem); + const menuDisabled = await this.stateService.getDisableContextMenuItem(); if (!menuDisabled) { await this.buildContextMenu(); } else { @@ -381,7 +375,7 @@ export default class MainBackground { async logout(expired: boolean) { await this.eventService.uploadEvents(); - const userId = this.activeAccount.userId; + const userId = await this.stateService.getUserId(); await Promise.all([ this.eventService.clearEvents(), @@ -461,7 +455,7 @@ export default class MainBackground { return; } - const currentVaultTimeout = await this.storageService.get(StorageKey.VaultTimeout); + const currentVaultTimeout = await this.stateService.getVaultTimeout(); if (currentVaultTimeout == null) { return; } @@ -524,7 +518,7 @@ export default class MainBackground { title: this.i18nService.t('copyPassword'), }); - if (this.activeAccount.canAccessPremium) { + if (await this.stateService.getCanAccessPremium()) { await this.contextMenusCreate({ type: 'normal', id: 'copy-totp', @@ -584,7 +578,7 @@ export default class MainBackground { }); } - const disableBadgeCounter = await this.storageService.get(StorageKey.DisableBadgeCounter); + const disableBadgeCounter = await this.stateService.getDisableBadgeCounter(); let theText = ''; if (!disableBadgeCounter) { @@ -611,7 +605,7 @@ export default class MainBackground { private async loadMenuAndUpdateBadgeForNoAccessState(contextMenuEnabled: boolean) { if (contextMenuEnabled) { - const authed = this.activeAccount.isAuthenticated; + const authed = await this.stateService.getIsAuthenticated(); await this.loadNoLoginsContextMenuOptions(this.i18nService.t(authed ? 'vaultLocked' : 'vaultLoggedOut')); } @@ -680,7 +674,7 @@ export default class MainBackground { }); } - const canAccessPremium = this.activeAccount.canAccessPremium; + const canAccessPremium = await this.stateService.getCanAccessPremium(); if (canAccessPremium && (cipher == null || (cipher.login.totp && cipher.login.totp !== ''))) { await this.contextMenusCreate({ type: 'normal', diff --git a/src/background/nativeMessaging.background.ts b/src/background/nativeMessaging.background.ts index 5af95b1395..c463bc87cd 100644 --- a/src/background/nativeMessaging.background.ts +++ b/src/background/nativeMessaging.background.ts @@ -1,15 +1,13 @@ -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { AppIdService } from 'jslib-common/abstractions/appId.service'; import { CryptoService } from 'jslib-common/abstractions/crypto.service'; import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service'; 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 { StateService } from 'jslib-common/abstractions/state.service'; import { StorageService } from 'jslib-common/abstractions/storage.service'; import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service'; -import { StorageKey } from 'jslib-common/enums/storageKey'; - import { Utils } from 'jslib-common/misc/utils'; import { SymmetricCryptoKey } from 'jslib-common/models/domain/symmetricCryptoKey'; @@ -32,24 +30,24 @@ export class NativeMessagingBackground { private appId: string; private validatingFingerprint: boolean; - constructor(private storageService: StorageService, private cryptoService: CryptoService, - private cryptoFunctionService: CryptoFunctionService, private vaultTimeoutService: VaultTimeoutService, + constructor(private cryptoService: CryptoService, + private cryptoFunctionService: CryptoFunctionService, private runtimeBackground: RuntimeBackground, private i18nService: I18nService, private messagingService: MessagingService, private appIdService: AppIdService, - private platformUtilsService: PlatformUtilsService, private activeAccount: ActiveAccountService) { - this.storageService.save(StorageKey.BiometricFingerprintValidated, false); + private platformUtilsService: PlatformUtilsService, private stateService: StateService) { + this.stateService.setBiometricFingerprintValidated(false); - if (chrome?.permissions?.onAdded) { - // Reload extension to activate nativeMessaging - chrome.permissions.onAdded.addListener(permissions => { - BrowserApi.reloadExtension(null); - }); - } + if (chrome?.permissions?.onAdded) { + // Reload extension to activate nativeMessaging + chrome.permissions.onAdded.addListener(permissions => { + BrowserApi.reloadExtension(null); + }); } + } async connect() { this.appId = await this.appIdService.getAppId(); - this.storageService.save(StorageKey.BiometricFingerprintValidated, false); + this.stateService.setBiometricFingerprintValidated(false); return new Promise((resolve, reject) => { this.port = BrowserApi.connectNative('com.8bit.bitwarden'); @@ -97,7 +95,7 @@ export class NativeMessagingBackground { if (this.validatingFingerprint) { this.validatingFingerprint = false; - this.storageService.save(StorageKey.BiometricFingerprintValidated, true); + this.stateService.setBiometricFingerprintValidated(true); } this.sharedSecret = new SymmetricCryptoKey(decrypted); this.secureSetupResolve(); @@ -179,7 +177,7 @@ export class NativeMessagingBackground { if (this.platformUtilsService.isSafari()) { this.postMessage(message); } else { - this.postMessage({appId: this.appId, message: await this.encryptMessage(message)}); + this.postMessage({ appId: this.appId, message: await this.encryptMessage(message) }); } } @@ -234,7 +232,7 @@ export class NativeMessagingBackground { switch (message.command) { case 'biometricUnlock': - await this.storageService.remove(StorageKey.BiometricAwaitingAcceptance); + await this.stateService.setBiometricAwaitingAcceptance(null); if (message.response === 'not enabled') { this.messagingService.send('showDialog', { @@ -254,16 +252,16 @@ export class NativeMessagingBackground { break; } - const enabled = await this.storageService.get(StorageKey.BiometricUnlock); + const enabled = await this.stateService.getBiometricUnlock(); if (enabled === null || enabled === false) { if (message.response === 'unlocked') { - await this.storageService.save(StorageKey.BiometricUnlock, true); + await this.stateService.setBiometricUnlock(true); } break; } // Ignore unlock if already unlockeded - if (!this.vaultTimeoutService.biometricLocked) { + if (!this.stateService.getBiometricLocked()) { break; } @@ -272,7 +270,7 @@ export class NativeMessagingBackground { // Verify key is correct by attempting to decrypt a secret try { - await this.cryptoService.getFingerprint(this.activeAccount.userId); + await this.cryptoService.getFingerprint(await this.stateService.getUserId()); } catch (e) { // tslint:disable-next-line console.error('Unable to verify key:', e); @@ -283,8 +281,8 @@ export class NativeMessagingBackground { break; } - this.vaultTimeoutService.biometricLocked = false; - this.runtimeBackground.processMessage({command: 'unlocked'}, null, null); + await this.stateService.setBiometricLocked(false); + this.runtimeBackground.processMessage({ command: 'unlocked' }, null, null); } break; default: @@ -305,7 +303,7 @@ export class NativeMessagingBackground { this.sendUnencrypted({ command: 'setupEncryption', publicKey: Utils.fromBufferToB64(publicKey), - userId: this.activeAccount.userId, + userId: await this.stateService.getUserId(), }); return new Promise((resolve, reject) => this.secureSetupResolve = resolve); @@ -318,11 +316,11 @@ export class NativeMessagingBackground { message.timestamp = Date.now(); - this.postMessage({appId: this.appId, message: message}); + this.postMessage({ appId: this.appId, message: message }); } private async showFingerprintDialog() { - const fingerprint = (await this.cryptoService.getFingerprint(this.activeAccount.userId, this.publicKey)).join(' '); + const fingerprint = (await this.cryptoService.getFingerprint(await this.stateService.getUserId(), this.publicKey)).join(' '); this.messagingService.send('showDialog', { html: `${this.i18nService.t('desktopIntegrationVerificationText')}

${fingerprint}`, diff --git a/src/background/runtime.background.ts b/src/background/runtime.background.ts index cea7b5fd87..e8c8551c48 100644 --- a/src/background/runtime.background.ts +++ b/src/background/runtime.background.ts @@ -24,7 +24,7 @@ import MainBackground from './main.background'; import { Utils } from 'jslib-common/misc/utils'; import { PolicyType } from 'jslib-common/enums/policyType'; -import { StorageKey } from 'jslib-common/enums/storageKey'; +import { StateService } from 'jslib-common/abstractions/state.service'; export default class RuntimeBackground { private runtime: any; @@ -34,11 +34,11 @@ export default class RuntimeBackground { constructor(private main: MainBackground, private autofillService: AutofillService, private cipherService: CipherService, private platformUtilsService: BrowserPlatformUtilsService, - private storageService: StorageService, private i18nService: I18nService, + private i18nService: I18nService, private notificationsService: NotificationsService, private systemService: SystemService, private vaultTimeoutService: VaultTimeoutService, private environmentService: EnvironmentService, private policyService: PolicyService, private messagingService: MessagingService, - private folderService: FolderService) { + private folderService: FolderService, private stateService: StateService) { // onInstalled listener must be wired up before anything else, so we do it in the ctor chrome.runtime.onInstalled.addListener((details: any) => { @@ -328,8 +328,7 @@ export default class RuntimeBackground { const usernameMatches = ciphers.filter(c => c.login.username != null && c.login.username.toLowerCase() === normalizedUsername); if (usernameMatches.length === 0) { - const disabledAddLogin = await this.storageService.get( - StorageKey.DisableAddLoginNotification); + const disabledAddLogin = await this.stateService.getDisableAddLoginNotification(); if (disabledAddLogin) { return; } @@ -351,8 +350,7 @@ export default class RuntimeBackground { }); await this.main.checkNotificationQueue(tab); } else if (usernameMatches.length === 1 && usernameMatches[0].login.password !== loginInfo.password) { - const disabledChangePassword = await this.storageService.get( - StorageKey.DisableChangedPasswordNotification); + const disabledChangePassword = await this.stateService.getDisableChangedPasswordNotification(); if (disabledChangePassword) { return; } @@ -422,30 +420,27 @@ export default class RuntimeBackground { private async setDefaultSettings() { // Default timeout option to "on restart". - const currentVaultTimeout = await this.storageService.get(StorageKey.VaultTimeout); + const currentVaultTimeout = await this.stateService.getVaultTimeout(); if (currentVaultTimeout == null) { - await this.storageService.save(StorageKey.VaultTimeout, -1); + await this.stateService.setVaultTimeout(-1); } // Default action to "lock". - const currentVaultTimeoutAction = await this.storageService.get(StorageKey.VaultTimeoutAction); + const currentVaultTimeoutAction = await this.stateService.getVaultTimeoutAction(); if (currentVaultTimeoutAction == null) { - await this.storageService.save(StorageKey.VaultTimeoutAction, 'lock'); + await this.stateService.setVaultTimeoutAction('lock'); } } private async getDataForTab(tab: any, responseCommand: string) { const responseData: any = {}; if (responseCommand === 'notificationBarDataResponse') { - responseData.neverDomains = await this.storageService.get(StorageKey.NeverDomains); - const disableAddLoginFromOptions = await this.storageService.get( - StorageKey.DisableAddLoginNotification); + responseData.neverDomains = await this.stateService.getNeverDomains(); + const disableAddLoginFromOptions = await this.stateService.getDisableAddLoginNotification(); responseData.disabledAddLoginNotification = disableAddLoginFromOptions || !(await this.allowPersonalOwnership()); - responseData.disabledChangedPasswordNotification = await this.storageService.get( - StorageKey.DisableChangedPasswordNotification); + responseData.disabledChangedPasswordNotification = await this.stateService.getDisableChangedPasswordNotification(); } else if (responseCommand === 'autofillerAutofillOnPageLoadEnabledResponse') { - responseData.autofillEnabled = await this.storageService.get( - StorageKey.EnableAutoFillOnPageLoad); + responseData.autofillEnabled = await this.stateService.getEnableAutoFillOnPageLoad(); } else if (responseCommand === 'notificationBarFrameDataResponse') { responseData.i18n = { appName: this.i18nService.t('appName'), diff --git a/src/popup/accounts/hint.component.ts b/src/popup/accounts/hint.component.ts index 144b3fd4ff..1a66f62cda 100644 --- a/src/popup/accounts/hint.component.ts +++ b/src/popup/accounts/hint.component.ts @@ -6,6 +6,7 @@ import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { HintComponent as BaseHintComponent } from 'jslib-angular/components/hint.component'; +import { LogService } from 'jslib-common/abstractions/log.service'; @Component({ selector: 'app-hint', @@ -13,7 +14,7 @@ import { HintComponent as BaseHintComponent } from 'jslib-angular/components/hin }) export class HintComponent extends BaseHintComponent { constructor(router: Router, platformUtilsService: PlatformUtilsService, - i18nService: I18nService, apiService: ApiService) { - super(router, i18nService, apiService, platformUtilsService); + i18nService: I18nService, apiService: ApiService, logService: LogService) { + super(router, i18nService, apiService, platformUtilsService, logService); } } diff --git a/src/popup/accounts/home.component.ts b/src/popup/accounts/home.component.ts index 90cd5eecd2..2b184e2c02 100644 --- a/src/popup/accounts/home.component.ts +++ b/src/popup/accounts/home.component.ts @@ -1,22 +1,20 @@ import { Component } from '@angular/core'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service'; import { EnvironmentService } from 'jslib-common/abstractions/environment.service'; import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { Utils } from 'jslib-common/misc/utils'; -import { StorageKey } from 'jslib-common/enums/storageKey'; - @Component({ selector: 'app-home', templateUrl: 'home.component.html', }) export class HomeComponent { constructor(protected platformUtilsService: PlatformUtilsService, - private passwordGenerationService: PasswordGenerationService, private activeAccount: ActiveAccountService, + private passwordGenerationService: PasswordGenerationService, private stateService: StateService, private cryptoFunctionService: CryptoFunctionService, private environmentService: EnvironmentService) { } async launchSsoBrowser() { @@ -35,8 +33,8 @@ export class HomeComponent { const codeVerifierHash = await this.cryptoFunctionService.hash(codeVerifier, 'sha256'); const codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash); - await this.activeAccount.saveInformation(StorageKey.SsoCodeVerifier, codeVerifier); - await this.activeAccount.saveInformation(StorageKey.SsoState, state); + await this.stateService.setSsoCodeVerifier(codeVerifier); + await this.stateService.setSsoState(state); let url = this.environmentService.getWebVaultUrl(); if (url == null) { diff --git a/src/popup/accounts/lock.component.ts b/src/popup/accounts/lock.component.ts index dbd56408e1..9626b873cc 100644 --- a/src/popup/accounts/lock.component.ts +++ b/src/popup/accounts/lock.component.ts @@ -1,7 +1,6 @@ import { Component } from '@angular/core'; import { Router } from '@angular/router'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { ApiService } from 'jslib-common/abstractions/api.service'; import { CryptoService } from 'jslib-common/abstractions/crypto.service'; import { EnvironmentService } from 'jslib-common/abstractions/environment.service'; @@ -14,7 +13,8 @@ import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.serv import { LockComponent as BaseLockComponent } from 'jslib-angular/components/lock.component'; import Swal from 'sweetalert2'; -import { StorageKey } from 'jslib-common/enums/storageKey'; +import { LogService } from 'jslib-common/abstractions/log.service'; +import { KeyConnectorService } from 'jslib-common/abstractions/keyConnector.service'; @Component({ selector: 'app-lock', @@ -24,21 +24,19 @@ export class LockComponent extends BaseLockComponent { private isInitialLockScreen: boolean; constructor(router: Router, i18nService: I18nService, - platformUtilsService: PlatformUtilsService, messagingService: MessagingService, - activeAccount: ActiveAccountService, cryptoService: CryptoService, + platformUtilsService: PlatformUtilsService, messagingService: MessagingService, cryptoService: CryptoService, vaultTimeoutService: VaultTimeoutService, environmentService: EnvironmentService, - stateService: StateService, apiService: ApiService) { + stateService: StateService, apiService: ApiService, logService: LogService, keyConnectorService: KeyConnectorService) { super(router, i18nService, platformUtilsService, messagingService, cryptoService, vaultTimeoutService, - environmentService, stateService, apiService, activeAccount); + environmentService, stateService, apiService, logService, keyConnectorService); this.successRoute = '/tabs/current'; this.isInitialLockScreen = (window as any).previousPopupUrl == null; } async ngOnInit() { await super.ngOnInit(); - const disableAutoBiometricsPrompt = await this.activeAccount.getInformation( - StorageKey.DisableAutoBiometricsPrompt) ?? true; + const disableAutoBiometricsPrompt = await this.stateService.getDisableAutoBiometricsPrompt() ?? true; window.setTimeout(async () => { document.getElementById(this.pinLock ? 'pin' : 'masterPassword').focus(); diff --git a/src/popup/accounts/login.component.ts b/src/popup/accounts/login.component.ts index 2b697c2488..595befcab8 100644 --- a/src/popup/accounts/login.component.ts +++ b/src/popup/accounts/login.component.ts @@ -1,7 +1,6 @@ import { Component } from '@angular/core'; import { Router } from '@angular/router'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { AuthService } from 'jslib-common/abstractions/auth.service'; import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service'; import { EnvironmentService } from 'jslib-common/abstractions/environment.service'; @@ -13,6 +12,7 @@ import { StorageService } from 'jslib-common/abstractions/storage.service'; import { SyncService } from 'jslib-common/abstractions/sync.service'; import { LoginComponent as BaseLoginComponent } from 'jslib-angular/components/login.component'; +import { LogService } from 'jslib-common/abstractions/log.service'; @Component({ selector: 'app-login', @@ -23,11 +23,11 @@ export class LoginComponent extends BaseLoginComponent { protected platformUtilsService: PlatformUtilsService, protected i18nService: I18nService, protected stateService: StateService, protected environmentService: EnvironmentService, protected passwordGenerationService: PasswordGenerationService, - protected cryptoFunctionService: CryptoFunctionService, storageService: StorageService, - syncService: SyncService, protected activeAccount: ActiveAccountService) { + protected cryptoFunctionService: CryptoFunctionService, logService: LogService, + syncService: SyncService) { super(authService, router, platformUtilsService, i18nService, stateService, environmentService, passwordGenerationService, cryptoFunctionService, - storageService, activeAccount); + logService); super.onSuccessfulLogin = async () => { await syncService.fullSync(true); }; diff --git a/src/popup/accounts/register.component.ts b/src/popup/accounts/register.component.ts index 75fbdca157..d91df1d326 100644 --- a/src/popup/accounts/register.component.ts +++ b/src/popup/accounts/register.component.ts @@ -11,6 +11,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se import { StateService } from 'jslib-common/abstractions/state.service'; import { RegisterComponent as BaseRegisterComponent } from 'jslib-angular/components/register.component'; +import { LogService } from 'jslib-common/abstractions/log.service'; @Component({ selector: 'app-register', @@ -20,8 +21,8 @@ export class RegisterComponent extends BaseRegisterComponent { constructor(authService: AuthService, router: Router, i18nService: I18nService, cryptoService: CryptoService, apiService: ApiService, stateService: StateService, platformUtilsService: PlatformUtilsService, - passwordGenerationService: PasswordGenerationService, environmentService: EnvironmentService) { + passwordGenerationService: PasswordGenerationService, environmentService: EnvironmentService, logService: LogService) { super(authService, router, i18nService, cryptoService, apiService, stateService, platformUtilsService, - passwordGenerationService, environmentService); + passwordGenerationService, environmentService, logService); } } diff --git a/src/popup/accounts/set-password.component.ts b/src/popup/accounts/set-password.component.ts index 814a7287a1..ba124cb14f 100644 --- a/src/popup/accounts/set-password.component.ts +++ b/src/popup/accounts/set-password.component.ts @@ -5,7 +5,6 @@ import { Router, } from '@angular/router'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { ApiService } from 'jslib-common/abstractions/api.service'; import { CryptoService } from 'jslib-common/abstractions/crypto.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; @@ -13,6 +12,7 @@ import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { PolicyService } from 'jslib-common/abstractions/policy.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { SyncService } from 'jslib-common/abstractions/sync.service'; import { @@ -26,11 +26,11 @@ import { export class SetPasswordComponent extends BaseSetPasswordComponent { constructor(apiService: ApiService, i18nService: I18nService, cryptoService: CryptoService, messagingService: MessagingService, - activeAccount: ActiveAccountService, passwordGenerationService: PasswordGenerationService, + stateService: StateService, passwordGenerationService: PasswordGenerationService, platformUtilsService: PlatformUtilsService, policyService: PolicyService, router: Router, syncService: SyncService, route: ActivatedRoute) { super(i18nService, cryptoService, messagingService, passwordGenerationService, - platformUtilsService, policyService, router, apiService, syncService, route, activeAccount); + platformUtilsService, policyService, router, apiService, syncService, route, stateService); } get masterPasswordScoreWidth() { diff --git a/src/popup/accounts/sso.component.ts b/src/popup/accounts/sso.component.ts index 34b3a77c01..f51f126a9e 100644 --- a/src/popup/accounts/sso.component.ts +++ b/src/popup/accounts/sso.component.ts @@ -18,6 +18,7 @@ import { SyncService } from 'jslib-common/abstractions/sync.service'; import { SsoComponent as BaseSsoComponent } from 'jslib-angular/components/sso.component'; import { BrowserApi } from '../../browser/browserApi'; +import { LogService } from 'jslib-common/abstractions/log.service'; @Component({ selector: 'app-sso', @@ -29,9 +30,9 @@ export class SsoComponent extends BaseSsoComponent { storageService: StorageService, stateService: StateService, platformUtilsService: PlatformUtilsService, apiService: ApiService, cryptoFunctionService: CryptoFunctionService, passwordGenerationService: PasswordGenerationService, - syncService: SyncService, environmentService: EnvironmentService) { - super(authService, router, i18nService, route, storageService, stateService, platformUtilsService, - apiService, cryptoFunctionService, environmentService, passwordGenerationService); + syncService: SyncService, environmentService: EnvironmentService, logService: LogService) { + super(authService, router, i18nService, route, stateService, platformUtilsService, + apiService, cryptoFunctionService, environmentService, passwordGenerationService, logService); const url = this.environmentService.getWebVaultUrl(); diff --git a/src/popup/accounts/two-factor.component.ts b/src/popup/accounts/two-factor.component.ts index 7850daa5d9..c713391670 100644 --- a/src/popup/accounts/two-factor.component.ts +++ b/src/popup/accounts/two-factor.component.ts @@ -28,6 +28,7 @@ import { TwoFactorComponent as BaseTwoFactorComponent } from 'jslib-angular/comp import { PopupUtilsService } from '../services/popup-utils.service'; import { BrowserApi } from '../../browser/browserApi'; +import { LogService } from 'jslib-common/abstractions/log.service'; const BroadcasterSubscriptionId = 'TwoFactorComponent'; @@ -43,10 +44,10 @@ export class TwoFactorComponent extends BaseTwoFactorComponent { platformUtilsService: PlatformUtilsService, private syncService: SyncService, environmentService: EnvironmentService, private ngZone: NgZone, private broadcasterService: BroadcasterService, private changeDetectorRef: ChangeDetectorRef, - private popupUtilsService: PopupUtilsService, stateService: StateService, - storageService: StorageService, route: ActivatedRoute, private messagingService: MessagingService) { + private popupUtilsService: PopupUtilsService, stateService: StateService, route: ActivatedRoute, + private messagingService: MessagingService, logService: LogService) { super(authService, router, i18nService, apiService, platformUtilsService, window, environmentService, - stateService, storageService, route); + stateService, route, logService); super.onSuccessfulLogin = () => { return syncService.fullSync(true); }; diff --git a/src/popup/accounts/update-temp-password.component.ts b/src/popup/accounts/update-temp-password.component.ts index 63702cc55c..9ed9378409 100644 --- a/src/popup/accounts/update-temp-password.component.ts +++ b/src/popup/accounts/update-temp-password.component.ts @@ -1,6 +1,5 @@ import { Component } from '@angular/core'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { ApiService } from 'jslib-common/abstractions/api.service'; import { CryptoService } from 'jslib-common/abstractions/crypto.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; @@ -11,6 +10,8 @@ import { PolicyService } from 'jslib-common/abstractions/policy.service'; import { SyncService } from 'jslib-common/abstractions/sync.service'; import { UpdateTempPasswordComponent as BaseUpdateTempPasswordComponent } from 'jslib-angular/components/update-temp-password.component'; +import { StateService } from 'jslib-common/abstractions/state.service'; +import { LogService } from 'jslib-common/abstractions/log.service'; interface MasterPasswordScore { Color: string; @@ -55,11 +56,11 @@ export class UpdateTempPasswordComponent extends BaseUpdateTempPasswordComponent constructor(i18nService: I18nService, platformUtilsService: PlatformUtilsService, passwordGenerationService: PasswordGenerationService, policyService: PolicyService, - cryptoService: CryptoService, activeAccount: ActiveAccountService, + cryptoService: CryptoService, stateService: StateService, messagingService: MessagingService, apiService: ApiService, - syncService: SyncService) { + syncService: SyncService, logService: LogService) { super(i18nService, platformUtilsService, passwordGenerationService, policyService, - cryptoService, messagingService, apiService, activeAccount, - syncService); + cryptoService, messagingService, apiService, stateService, + syncService, logService); } } diff --git a/src/popup/app.component.ts b/src/popup/app.component.ts index ded3b11b58..c9caa5b515 100644 --- a/src/popup/app.component.ts +++ b/src/popup/app.component.ts @@ -31,8 +31,6 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se import { StateService } from 'jslib-common/abstractions/state.service'; import { StorageService } from 'jslib-common/abstractions/storage.service'; -import { StorageKey } from 'jslib-common/enums/storageKey'; - import { routerTransition } from './app-routing.animations'; @Component({ @@ -81,7 +79,7 @@ export class AppComponent implements OnInit { (window as any).bitwardenPopupMainMessageListener = async (msg: any, sender: any, sendResponse: any) => { if (msg.command === 'doneLoggingOut') { this.ngZone.run(async () => { - this.authService.logOut(() => { + this.authService.logOut(async () => { if (msg.expired) { this.showToast({ type: 'warning', @@ -90,7 +88,7 @@ export class AppComponent implements OnInit { }); } this.router.navigate(['home']); - this.stateService.purge(); + await this.stateService.clean(); }); this.changeDetectorRef.detectChanges(); }); @@ -99,7 +97,7 @@ export class AppComponent implements OnInit { this.router.navigate(['home']); }); } else if (msg.command === 'locked') { - this.stateService.purge(); + this.stateService.clean(); this.ngZone.run(() => { this.router.navigate(['lock']); }); @@ -133,15 +131,13 @@ export class AppComponent implements OnInit { const url = event.urlAfterRedirects || event.url || ''; if (url.startsWith('/tabs/') && (window as any).previousPopupUrl != null && (window as any).previousPopupUrl.startsWith('/tabs/')) { - this.stateService.remove('GroupingsComponent'); - this.stateService.remove('GroupingsComponentScope'); - this.stateService.remove('CiphersComponent'); - this.stateService.remove('SendGroupingsComponent'); - this.stateService.remove('SendGroupingsComponentScope'); - this.stateService.remove('SendTypeComponent'); + this.stateService.setBrowserGroupingComponentState(null); + this.stateService.setBrowserCipherComponentState(null); + this.stateService.setBrowserSendComponentState(null); + this.stateService.setBrowserSendTypeComponentState(null); } if (url.startsWith('/tabs/')) { - this.stateService.remove('addEditCipherInfo'); + this.stateService.setAddEditCipherInfo(null); } (window as any).previousPopupUrl = url; @@ -173,7 +169,7 @@ export class AppComponent implements OnInit { } this.lastActivity = now; - this.storageService.save(StorageKey.LastActive, now); + await this.stateService.setLastActive(now); } private showToast(msg: any) { diff --git a/src/popup/components/action-buttons.component.ts b/src/popup/components/action-buttons.component.ts index f959bdf501..a01b5854cf 100644 --- a/src/popup/components/action-buttons.component.ts +++ b/src/popup/components/action-buttons.component.ts @@ -13,12 +13,12 @@ import { EventType } from 'jslib-common/enums/eventType'; import { CipherView } from 'jslib-common/models/view/cipherView'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { EventService } from 'jslib-common/abstractions/event.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { PasswordRepromptService } from 'jslib-common/abstractions/passwordReprompt.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { TotpService } from 'jslib-common/abstractions/totp.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; @Component({ selector: 'app-action-buttons', @@ -35,11 +35,11 @@ export class ActionButtonsComponent { constructor(private toasterService: ToasterService, private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, private eventService: EventService, - private totpService: TotpService, private activeAccount: ActiveAccountService, + private totpService: TotpService, private stateService: StateService, private passwordRepromptService: PasswordRepromptService) { } async ngOnInit() { - this.userHasPremiumAccess = this.activeAccount.canAccessPremium; + this.userHasPremiumAccess = await this.stateService.getCanAccessPremium(); } launchCipher() { diff --git a/src/popup/generator/password-generator.component.ts b/src/popup/generator/password-generator.component.ts index 6fffda8b41..7afa6caf09 100644 --- a/src/popup/generator/password-generator.component.ts +++ b/src/popup/generator/password-generator.component.ts @@ -27,7 +27,7 @@ export class PasswordGeneratorComponent extends BasePasswordGeneratorComponent { async ngOnInit() { await super.ngOnInit(); - const addEditCipherInfo = await this.stateService.get('addEditCipherInfo'); + const addEditCipherInfo = await this.stateService.getAddEditCipherInfo(); if (addEditCipherInfo != null) { this.cipherState = addEditCipherInfo.cipher; } diff --git a/src/popup/send/send-add-edit.component.ts b/src/popup/send/send-add-edit.component.ts index 01f8cf417e..6ace22e00f 100644 --- a/src/popup/send/send-add-edit.component.ts +++ b/src/popup/send/send-add-edit.component.ts @@ -10,7 +10,6 @@ import { Router, } from '@angular/router'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { EnvironmentService } from 'jslib-common/abstractions/environment.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; @@ -22,6 +21,8 @@ import { TokenService } from 'jslib-common/abstractions/token.service'; import { PopupUtilsService } from '../services/popup-utils.service'; import { AddEditComponent as BaseAddEditComponent } from 'jslib-angular/components/send/add-edit.component'; +import { StateService } from 'jslib-common/abstractions/state.service'; +import { LogService } from 'jslib-common/abstractions/log.service'; @Component({ selector: 'app-send-add-edit', @@ -38,12 +39,12 @@ export class SendAddEditComponent extends BaseAddEditComponent { isUnsupportedMac = false; constructor(i18nService: I18nService, platformUtilsService: PlatformUtilsService, - activeAccount: ActiveAccountService, messagingService: MessagingService, policyService: PolicyService, + stateService: StateService, messagingService: MessagingService, policyService: PolicyService, environmentService: EnvironmentService, datePipe: DatePipe, sendService: SendService, private route: ActivatedRoute, private router: Router, private location: Location, - private popupUtilsService: PopupUtilsService) { + private popupUtilsService: PopupUtilsService, logService: LogService) { super(i18nService, platformUtilsService, environmentService, datePipe, - sendService, messagingService, policyService, activeAccount); + sendService, messagingService, policyService, logService, stateService); } get showFileSelector(): boolean { diff --git a/src/popup/send/send-groupings.component.ts b/src/popup/send/send-groupings.component.ts index 7baef8a291..9bc8554e65 100644 --- a/src/popup/send/send-groupings.component.ts +++ b/src/popup/send/send-groupings.component.ts @@ -26,6 +26,8 @@ import { BroadcasterService } from 'jslib-angular/services/broadcaster.service'; import { PopupUtilsService } from '../services/popup-utils.service'; import { SendType } from 'jslib-common/enums/sendType'; +import { LogService } from 'jslib-common/abstractions/log.service'; +import { BrowserSendComponentState } from 'jslib-common/models/domain/browserSendComponentState'; const ComponentId = 'SendComponent'; const ScopeStateId = ComponentId + 'Scope'; @@ -40,8 +42,7 @@ export class SendGroupingsComponent extends BaseSendComponent { // Send Type Calculations typeCounts = new Map(); // State Handling - state: any; - scopeState: any; + state: BrowserSendComponentState; private loadedTimeout: number; constructor(sendService: SendService, i18nService: I18nService, @@ -49,9 +50,10 @@ export class SendGroupingsComponent extends BaseSendComponent { policyService: PolicyService, searchService: SearchService, private popupUtils: PopupUtilsService, private stateService: StateService, private router: Router, private syncService: SyncService, - private changeDetectorRef: ChangeDetectorRef, private broadcasterService: BroadcasterService) { + private changeDetectorRef: ChangeDetectorRef, private broadcasterService: BroadcasterService, + logService: LogService) { super(sendService, i18nService, platformUtilsService, environmentService, ngZone, searchService, - policyService); + policyService, logService); super.onSuccessfulLoad = async () => { this.calculateTypeCounts(); this.selectAll(); @@ -62,12 +64,11 @@ export class SendGroupingsComponent extends BaseSendComponent { // Determine Header details this.showLeftHeader = !(this.popupUtils.inSidebar(window) && this.platformUtilsService.isFirefox()); // Clear state of Send Type Component - this.stateService.remove('SendTypeComponent'); + this.stateService.setBrowserSendComponentState(null); // Let super class finish await super.ngOnInit(); // Handle State Restore if necessary const restoredScopeState = await this.restoreState(); - this.state = (await this.stateService.get(ComponentId)) || {}; if (this.state.searchText != null) { this.searchText = this.state.searchText; } @@ -158,27 +159,25 @@ export class SendGroupingsComponent extends BaseSendComponent { this.state = { scrollY: this.popupUtils.getContentScrollY(window), searchText: this.searchText, - }; - await this.stateService.save(ComponentId, this.state); - - this.scopeState = { sends: this.sends, typeCounts: this.typeCounts, }; - await this.stateService.save(ScopeStateId, this.scopeState); + await this.stateService.setBrowserSendComponentState(this.state); } private async restoreState(): Promise { - this.scopeState = await this.stateService.get(ScopeStateId); - if (this.scopeState == null) { + this.state = await this.stateService.getBrowserSendComponentState(); + if (this.state == null) { return false; } - - if (this.scopeState.sends != null) { - this.sends = this.scopeState.sends; + if (this.state.sends != null) { + this.sends = this.state.sends; } - if (this.scopeState.typeCounts != null) { - this.typeCounts = this.scopeState.typeCounts; + if (this.state.typeCounts != null) { + this.typeCounts = this.state.typeCounts; + } + if (this.state.searchText != null) { + this.searchText = this.state.searchText; } return true; diff --git a/src/popup/send/send-type.component.ts b/src/popup/send/send-type.component.ts index 61f072aa96..6889637f46 100644 --- a/src/popup/send/send-type.component.ts +++ b/src/popup/send/send-type.component.ts @@ -28,6 +28,8 @@ import { BroadcasterService } from 'jslib-angular/services/broadcaster.service'; import { PopupUtilsService } from '../services/popup-utils.service'; import { SendType } from 'jslib-common/enums/sendType'; +import { LogService } from 'jslib-common/abstractions/log.service'; +import { BrowserComponentState } from 'jslib-common/models/domain/browserComponentState'; const ComponentId = 'SendTypeComponent'; @@ -38,7 +40,7 @@ const ComponentId = 'SendTypeComponent'; export class SendTypeComponent extends BaseSendComponent { groupingTitle: string; // State Handling - state: any; + state: BrowserComponentState; private refreshTimeout: number; private applySavedState = true; @@ -47,9 +49,9 @@ export class SendTypeComponent extends BaseSendComponent { policyService: PolicyService, searchService: SearchService, private popupUtils: PopupUtilsService, private stateService: StateService, private route: ActivatedRoute, private location: Location, private changeDetectorRef: ChangeDetectorRef, - private broadcasterService: BroadcasterService, private router: Router) { + private broadcasterService: BroadcasterService, private router: Router, logService: LogService) { super(sendService, i18nService, platformUtilsService, environmentService, ngZone, searchService, - policyService); + policyService, logService); super.onSuccessfulLoad = async () => { this.selectType(this.type); }; @@ -62,7 +64,7 @@ export class SendTypeComponent extends BaseSendComponent { await super.ngOnInit(); const queryParamsSub = this.route.queryParams.subscribe(async params => { if (this.applySavedState) { - this.state = (await this.stateService.get(ComponentId)) || {}; + this.state = (await this.stateService.getBrowserSendTypeComponentState()); if (this.state.searchText != null) { this.searchText = this.state.searchText; } @@ -87,7 +89,7 @@ export class SendTypeComponent extends BaseSendComponent { if (this.applySavedState && this.state != null) { window.setTimeout(() => this.popupUtils.setContentScrollY(window, this.state.scrollY), 0); } - this.stateService.remove(ComponentId); + this.stateService.setBrowserSendComponentState(null); // Unsubscribe if (queryParamsSub != null) { @@ -154,6 +156,6 @@ export class SendTypeComponent extends BaseSendComponent { scrollY: this.popupUtils.getContentScrollY(window), searchText: this.searchText, }; - await this.stateService.save(ComponentId, this.state); + await this.stateService.setBrowserSendTypeComponentState(this.state); } } diff --git a/src/popup/services/services.module.ts b/src/popup/services/services.module.ts index 40cdf23881..66dabc60b8 100644 --- a/src/popup/services/services.module.ts +++ b/src/popup/services/services.module.ts @@ -19,8 +19,6 @@ import { ValidationService } from 'jslib-angular/services/validation.service'; import { BrowserApi } from '../../browser/browserApi'; -import { AccountsManagementService } from 'jslib-common/abstractions/accountsManagement.service'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { ApiService } from 'jslib-common/abstractions/api.service'; import { AppIdService } from 'jslib-common/abstractions/appId.service'; import { AuditService } from 'jslib-common/abstractions/audit.service'; @@ -65,7 +63,6 @@ import { StateService } from 'jslib-common/services/state.service'; import { PopupSearchService } from './popup-search.service'; import { PopupUtilsService } from './popup-utils.service'; -import { StorageKey } from 'jslib-common/enums/storageKey'; import { ThemeType } from 'jslib-common/enums/themeType'; function getBgService(service: string) { @@ -77,14 +74,13 @@ function getBgService(service: string) { const isPrivateMode = BrowserApi.getBackgroundPage() == null; -const stateService = new StateService(); const messagingService = new BrowserMessagingService(); const searchService = isPrivateMode ? null : new PopupSearchService(getBgService('searchService')(), getBgService('cipherService')(), getBgService('consoleLogService')(), getBgService('i18nService')()); export function initFactory(platformUtilsService: PlatformUtilsService, i18nService: I18nService, storageService: StorageService, - popupUtilsService: PopupUtilsService): Function { + popupUtilsService: PopupUtilsService, stateService: StateService): Function { return async () => { if (!popupUtilsService.inPopup(window)) { window.document.body.classList.add('body-full'); @@ -95,17 +91,18 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ } if (!isPrivateMode) { - await stateService.save(StorageKey.DisableFavicon, - await storageService.get(StorageKey.DisableFavicon)); + // TODO: Fix these guys + // await stateService.save(StorageKey.DisableFavicon, + // await storageService.get(StorageKey.DisableFavicon)); - await stateService.save(StorageKey.DisableBadgeCounter, - await storageService.get(StorageKey.DisableBadgeCounter)); + // await stateService.save(StorageKey.DisableBadgeCounter, + // await storageService.get(StorageKey.DisableBadgeCounter)); const htmlEl = window.document.documentElement; const theme = await platformUtilsService.getEffectiveTheme(); htmlEl.classList.add('theme_' + theme); platformUtilsService.onDefaultSystemThemeChange(async sysTheme => { - const bwTheme = await storageService.get(StorageKey.Theme); + const bwTheme = await stateService.getTheme(); if (bwTheme == null || bwTheme === ThemeType.System) { htmlEl.classList.remove('theme_' + ThemeType.Light, 'theme_' + ThemeType.Dark); htmlEl.classList.add('theme_' + sysTheme); @@ -133,7 +130,7 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ ModalService, { provide: MessagingService, useValue: messagingService }, { provide: AuthServiceAbstraction, useFactory: getBgService('authService'), deps: [] }, - { provide: StateServiceAbstraction, useValue: stateService }, + { provide: StateServiceAbstraction, useFactory: getBgService('stateService') }, { provide: SearchServiceAbstraction, useValue: searchService }, { provide: AuditService, useFactory: getBgService('auditService'), deps: [] }, { provide: FileUploadService, useFactory: getBgService('fileUploadService'), deps: [] }, @@ -194,8 +191,6 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ }, { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, - { provide: ActiveAccountService, useFactory: getBgService('activeAccount'), deps: [] }, - { provide: AccountsManagementService, useFactory: getBgService('accountsManagementService'), deps: [] }, { provide: OrganizationService, useFactory: getBgService('organizationService'), deps: [] }, { provide: ProviderService, useFactory: getBgService('providerService'), deps: [] }, ], diff --git a/src/popup/settings/excluded-domains.component.ts b/src/popup/settings/excluded-domains.component.ts index f5bd2eb4a9..a6c92a6b56 100644 --- a/src/popup/settings/excluded-domains.component.ts +++ b/src/popup/settings/excluded-domains.component.ts @@ -7,9 +7,6 @@ import { import { Router } from '@angular/router'; -import { StorageKey } from 'jslib-common/enums/storageKey'; - -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; @@ -18,6 +15,7 @@ import { BroadcasterService } from 'jslib-angular/services/broadcaster.service'; import { BrowserApi } from '../../browser/browserApi'; import { Utils } from 'jslib-common/misc/utils'; +import { StateService } from 'jslib-common/abstractions/state.service'; interface ExcludedDomain { uri: string; @@ -35,14 +33,14 @@ export class ExcludedDomainsComponent implements OnInit, OnDestroy { currentUris: string[]; loadCurrentUrisTimeout: number; - constructor(private activeAccount: ActiveAccountService, + constructor(private stateService: StateService, private i18nService: I18nService, private router: Router, private broadcasterService: BroadcasterService, private ngZone: NgZone, private platformUtilsService: PlatformUtilsService) { } async ngOnInit() { - const savedDomains = await this.activeAccount.getInformation(StorageKey.NeverDomains); + const savedDomains = await this.stateService.getNeverDomains(); if (savedDomains) { for (const uri of Object.keys(savedDomains)) { this.excludedDomains.push({ uri: uri, showCurrentUris: false }); @@ -93,7 +91,7 @@ export class ExcludedDomainsComponent implements OnInit, OnDestroy { savedDomains[validDomain] = null; } } - await this.activeAccount.saveInformation(StorageKey.NeverDomains, savedDomains); + await this.stateService.setNeverDomains(savedDomains); this.router.navigate(['/tabs/settings']); } diff --git a/src/popup/settings/export.component.ts b/src/popup/settings/export.component.ts index 67a5f804a9..743b2e6ac8 100644 --- a/src/popup/settings/export.component.ts +++ b/src/popup/settings/export.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { Router } from '@angular/router'; +import { FormBuilder } from '@angular/forms'; import { CryptoService } from 'jslib-common/abstractions/crypto.service'; import { EventService } from 'jslib-common/abstractions/event.service'; @@ -9,6 +10,8 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se import { PolicyService } from 'jslib-common/abstractions/policy.service'; import { ExportComponent as BaseExportComponent } from 'jslib-angular/components/export.component'; +import { LogService } from 'jslib-common/abstractions/log.service'; +import { UserVerificationService } from 'jslib-common/abstractions/userVerification.service'; @Component({ selector: 'app-export', @@ -17,8 +20,10 @@ import { ExportComponent as BaseExportComponent } from 'jslib-angular/components export class ExportComponent extends BaseExportComponent { constructor(cryptoService: CryptoService, i18nService: I18nService, platformUtilsService: PlatformUtilsService, exportService: ExportService, - eventService: EventService, policyService: PolicyService, private router: Router) { - super(cryptoService, i18nService, platformUtilsService, exportService, eventService, policyService, window); + eventService: EventService, policyService: PolicyService, private router: Router, + logService: LogService, userVerificationService: UserVerificationService, formBuilder: FormBuilder) { + super(cryptoService, i18nService, platformUtilsService, exportService, eventService, + policyService, window, logService, userVerificationService, formBuilder); } protected saved() { diff --git a/src/popup/settings/folder-add-edit.component.ts b/src/popup/settings/folder-add-edit.component.ts index b6faa17173..1e723ab8ec 100644 --- a/src/popup/settings/folder-add-edit.component.ts +++ b/src/popup/settings/folder-add-edit.component.ts @@ -11,6 +11,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se import { FolderAddEditComponent as BaseFolderAddEditComponent, } from 'jslib-angular/components/folder-add-edit.component'; +import { LogService } from 'jslib-common/abstractions/log.service'; @Component({ selector: 'app-folder-add-edit', @@ -19,8 +20,8 @@ import { export class FolderAddEditComponent extends BaseFolderAddEditComponent { constructor(folderService: FolderService, i18nService: I18nService, platformUtilsService: PlatformUtilsService, private router: Router, - private route: ActivatedRoute) { - super(folderService, i18nService, platformUtilsService); + private route: ActivatedRoute, logService: LogService) { + super(folderService, i18nService, platformUtilsService, logService); } async ngOnInit() { diff --git a/src/popup/settings/options.component.ts b/src/popup/settings/options.component.ts index e3f1c01cb0..0d5537fb7b 100644 --- a/src/popup/settings/options.component.ts +++ b/src/popup/settings/options.component.ts @@ -3,14 +3,13 @@ import { OnInit, } from '@angular/core'; -import { StorageKey } from 'jslib-common/enums/storageKey'; import { ThemeType } from 'jslib-common/enums/themeType'; import { UriMatchType } from 'jslib-common/enums/uriMatchType'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { TotpService } from 'jslib-common/abstractions/totp.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; @Component({ selector: 'app-options', @@ -39,7 +38,7 @@ export class OptionsComponent implements OnInit { showAutofill: boolean = true; showDisplay: boolean = true; - constructor(private messagingService: MessagingService, private activeAccount: ActiveAccountService, + constructor(private messagingService: MessagingService, private stateService: StateService, private totpService: TotpService, i18nService: I18nService) { this.themeOptions = [ { name: i18nService.t('default'), value: null }, @@ -72,93 +71,85 @@ export class OptionsComponent implements OnInit { } async ngOnInit() { - this.enableAutoFillOnPageLoad = await this.activeAccount.getInformation( - StorageKey.EnableAutoFillOnPageLoad); + this.enableAutoFillOnPageLoad = await this.stateService.getEnableAutoFillOnPageLoad(); - this.autoFillOnPageLoadDefault = await this.activeAccount.getInformation( - StorageKey.AutoFillOnPageLoadDefault) ?? true; + this.autoFillOnPageLoadDefault = await this.stateService.getAutoFillOnPageLoadDefault() ?? true; - this.disableAddLoginNotification = await this.activeAccount.getInformation( - StorageKey.DisableAddLoginNotification); + this.disableAddLoginNotification = await this.stateService.getDisableAddLoginNotification(); - this.disableChangedPasswordNotification = await this.activeAccount.getInformation( - StorageKey.DisableChangedPasswordNotification); + this.disableChangedPasswordNotification = await this.stateService.getDisableChangedPasswordNotification(); - this.disableContextMenuItem = await this.activeAccount.getInformation( - StorageKey.DisableContextMenuItem); + this.disableContextMenuItem = await this.stateService.getDisableContextMenuItem(); - this.dontShowCards = await this.activeAccount.getInformation(StorageKey.DontShowCardsCurrentTab); - this.dontShowIdentities = await this.activeAccount.getInformation(StorageKey.DontShowIdentitiesCurrentTab); + this.dontShowCards = await this.stateService.getDontShowCardsCurrentTab(); + this.dontShowIdentities = await this.stateService.getDontShowIdentitiesCurrentTab(); this.disableAutoTotpCopy = !(await this.totpService.isAutoCopyEnabled()); - this.disableFavicon = await this.activeAccount.getInformation(StorageKey.DisableFavicon); + this.disableFavicon = await this.stateService.getDisableFavicon(); - this.disableBadgeCounter = await this.activeAccount.getInformation(StorageKey.DisableBadgeCounter); + this.disableBadgeCounter = await this.stateService.getDisableBadgeCounter(); - this.theme = await this.activeAccount.getInformation(StorageKey.Theme); + this.theme = await this.stateService.getTheme(); - const defaultUriMatch = await this.activeAccount.getInformation(StorageKey.DefaultUriMatch); + const defaultUriMatch = await this.stateService.getDefaultUriMatch(); this.defaultUriMatch = defaultUriMatch == null ? UriMatchType.Domain : defaultUriMatch; - this.clearClipboard = await this.activeAccount.getInformation(StorageKey.ClearClipboard); + this.clearClipboard = await this.stateService.getClearClipboard(); } async updateAddLoginNotification() { - await this.activeAccount.saveInformation(StorageKey.DisableAddLoginNotification, - this.disableAddLoginNotification); + await this.stateService.setDisableAddLoginNotification(this.disableAddLoginNotification); } async updateChangedPasswordNotification() { - await this.activeAccount.saveInformation(StorageKey.DisableChangedPasswordNotification, - this.disableChangedPasswordNotification); + await this.stateService.setDisableChangedPasswordNotification(this.disableChangedPasswordNotification); } async updateDisableContextMenuItem() { - await this.activeAccount.saveInformation(StorageKey.DisableContextMenuItem, - this.disableContextMenuItem); + await this.stateService.setDisableContextMenuItem(this.disableContextMenuItem); this.messagingService.send('bgUpdateContextMenu'); } async updateAutoTotpCopy() { - await this.activeAccount.saveInformation(StorageKey.DisableAutoTotpCopy, this.disableAutoTotpCopy); + await this.stateService.setDisableAutoTotpCopy(this.disableAutoTotpCopy); } async updateAutoFillOnPageLoad() { - await this.activeAccount.saveInformation(StorageKey.EnableAutoFillOnPageLoad, this.enableAutoFillOnPageLoad); + await this.stateService.setEnableAutoFillOnPageLoad(this.enableAutoFillOnPageLoad); } async updateAutoFillOnPageLoadDefault() { - await this.activeAccount.saveInformation(StorageKey.AutoFillOnPageLoadDefault, this.autoFillOnPageLoadDefault); + await this.stateService.setAutoFillOnPageLoadDefault(this.autoFillOnPageLoadDefault); } async updateDisableFavicon() { - await this.activeAccount.saveInformation(StorageKey.DisableFavicon, this.disableFavicon); + await this.stateService.setDisableFavicon(this.disableFavicon); } async updateDisableBadgeCounter() { - await this.activeAccount.saveInformation(StorageKey.DisableBadgeCounter, this.disableBadgeCounter); + await this.stateService.setDisableBadgeCounter(this.disableBadgeCounter); this.messagingService.send('bgUpdateContextMenu'); } async updateShowCards() { - await this.activeAccount.saveInformation(StorageKey.DontShowCardsCurrentTab, this.dontShowCards); + await this.stateService.setDontShowCardsCurrentTab(this.dontShowCards); } async updateShowIdentities() { - await this.activeAccount.saveInformation(StorageKey.DontShowIdentitiesCurrentTab, this.dontShowIdentities); + await this.stateService.setDontShowIdentitiesCurrentTab(this.dontShowIdentities); } async saveTheme() { - await this.activeAccount.saveInformation(StorageKey.Theme, this.theme); + await this.stateService.setTheme(this.theme); window.setTimeout(() => window.location.reload(), 200); } async saveDefaultUriMatch() { - await this.activeAccount.saveInformation(StorageKey.DefaultUriMatch, this.defaultUriMatch); + await this.stateService.setDefaultUriMatch(this.defaultUriMatch); } async saveClearClipboard() { - await this.activeAccount.saveInformation(StorageKey.ClearClipboard, this.clearClipboard); + await this.stateService.setClearClipboard(this.clearClipboard); } } diff --git a/src/popup/settings/premium.component.ts b/src/popup/settings/premium.component.ts index 411b1caaf9..9e7383bdef 100644 --- a/src/popup/settings/premium.component.ts +++ b/src/popup/settings/premium.component.ts @@ -1,12 +1,13 @@ import { CurrencyPipe } from '@angular/common'; import { Component } from '@angular/core'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { ApiService } from 'jslib-common/abstractions/api.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { PremiumComponent as BasePremiumComponent } from 'jslib-angular/components/premium.component'; +import { StateService } from 'jslib-common/abstractions/state.service'; +import { LogService } from 'jslib-common/abstractions/log.service'; @Component({ selector: 'app-premium', @@ -16,9 +17,9 @@ export class PremiumComponent extends BasePremiumComponent { priceString: string; constructor(i18nService: I18nService, platformUtilsService: PlatformUtilsService, - apiService: ApiService, activeAccount: ActiveAccountService, + apiService: ApiService, logService: LogService, stateService: StateService, private currencyPipe: CurrencyPipe) { - super(i18nService, platformUtilsService, apiService, activeAccount); + super(i18nService, platformUtilsService, apiService, logService, stateService); // Support old price string. Can be removed in future once all translations are properly updated. const thePrice = this.currencyPipe.transform(this.price, '$'); diff --git a/src/popup/settings/settings.component.ts b/src/popup/settings/settings.component.ts index 1795994b49..d5dadd6111 100644 --- a/src/popup/settings/settings.component.ts +++ b/src/popup/settings/settings.component.ts @@ -12,9 +12,7 @@ import Swal from 'sweetalert2/src/sweetalert2.js'; import { BrowserApi } from '../../browser/browserApi'; import { DeviceType } from 'jslib-common/enums/deviceType'; -import { StorageKey } from 'jslib-common/enums/storageKey'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { CryptoService } from 'jslib-common/abstractions/crypto.service'; import { EnvironmentService } from 'jslib-common/abstractions/environment.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; @@ -26,6 +24,7 @@ import { PopupUtilsService } from '../services/popup-utils.service'; import { ModalService } from 'jslib-angular/services/modal.service'; import { SetPinComponent } from '../components/set-pin.component'; +import { StateService } from 'jslib-common/abstractions/state.service'; const RateUrls = { [DeviceType.ChromeExtension]: @@ -62,7 +61,7 @@ export class SettingsComponent implements OnInit { constructor(private platformUtilsService: PlatformUtilsService, private i18nService: I18nService, private vaultTimeoutService: VaultTimeoutService, public messagingService: MessagingService, private router: Router, private environmentService: EnvironmentService, - private cryptoService: CryptoService, private activeAccount: ActiveAccountService, + private cryptoService: CryptoService, private stateService: StateService, private popupUtilsService: PopupUtilsService, private modalService: ModalService, private toasterService: ToasterService) { } @@ -106,7 +105,7 @@ export class SettingsComponent implements OnInit { this.saveVaultTimeout(value); }); - const action = await this.activeAccount.getInformation(StorageKey.VaultTimeoutAction); + const action = await this.stateService.getVaultTimeoutAction(); this.vaultTimeoutAction = action == null ? 'lock' : action; const pinSet = await this.vaultTimeoutService.isPinLockSet(); @@ -114,8 +113,7 @@ export class SettingsComponent implements OnInit { this.supportsBiometric = await this.platformUtilsService.supportsBiometric(); this.biometric = await this.vaultTimeoutService.isBiometricLockSet(); - this.disableAutoBiometricsPrompt = await this.activeAccount.getInformation( - StorageKey.DisableAutoBiometricsPrompt) ?? true; + this.disableAutoBiometricsPrompt = await this.stateService.getDisableAutoBiometricsPrompt() ?? true; } async saveVaultTimeout(newValue: number) { @@ -223,14 +221,14 @@ export class SettingsComponent implements OnInit { allowOutsideClick: false, }); - await this.activeAccount.saveInformation(StorageKey.BiometricAwaitingAcceptance, true); + await this.stateService.setBiometricAwaitingAcceptance(true); await this.cryptoService.toggleKey(); await Promise.race([ - submitted.then(result => { + submitted.then(async result => { if (result.dismiss === Swal.DismissReason.cancel) { this.biometric = false; - this.activeAccount.removeInformation(StorageKey.BiometricAwaitingAcceptance); + await this.stateService.setBiometricAwaitingAcceptance(null); } }), this.platformUtilsService.authenticateBiometric().then(result => { @@ -246,13 +244,13 @@ export class SettingsComponent implements OnInit { }), ]); } else { - await this.activeAccount.removeInformation(StorageKey.BiometricUnlock); - this.vaultTimeoutService.biometricLocked = false; + await this.stateService.setBiometricUnlock(null); + await this.stateService.setBiometricLocked(false); } } async updateAutoBiometricsPrompt() { - await this.activeAccount.saveInformation(StorageKey.DisableAutoBiometricsPrompt, this.disableAutoBiometricsPrompt); + await this.stateService.setDisableAutoBiometricsPrompt(this.disableAutoBiometricsPrompt); } async lock() { @@ -332,7 +330,7 @@ export class SettingsComponent implements OnInit { } async fingerprint() { - const fingerprint = await this.cryptoService.getFingerprint(this.activeAccount.userId); + const fingerprint = await this.cryptoService.getFingerprint(await this.stateService.getUserId()); const p = document.createElement('p'); p.innerText = this.i18nService.t('yourAccountsFingerprint') + ':'; const p2 = document.createElement('p'); diff --git a/src/popup/vault/add-edit.component.ts b/src/popup/vault/add-edit.component.ts index 1ac493569b..dac43fa61d 100644 --- a/src/popup/vault/add-edit.component.ts +++ b/src/popup/vault/add-edit.component.ts @@ -7,7 +7,6 @@ import { import { BrowserApi } from '../../browser/browserApi'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { AuditService } from 'jslib-common/abstractions/audit.service'; import { CipherService } from 'jslib-common/abstractions/cipher.service'; import { CollectionService } from 'jslib-common/abstractions/collection.service'; @@ -27,7 +26,8 @@ import { LoginUriView } from 'jslib-common/models/view/loginUriView'; import { AddEditComponent as BaseAddEditComponent } from 'jslib-angular/components/add-edit.component'; import { CipherType } from 'jslib-common/enums/cipherType'; -import { StorageKey } from 'jslib-common/enums/storageKey'; +import { PasswordRepromptService } from 'jslib-common/abstractions/passwordReprompt.service'; +import { LogService } from 'jslib-common/abstractions/log.service'; @Component({ selector: 'app-vault-add-edit', @@ -41,15 +41,15 @@ export class AddEditComponent extends BaseAddEditComponent { constructor(cipherService: CipherService, folderService: FolderService, i18nService: I18nService, platformUtilsService: PlatformUtilsService, - auditService: AuditService, stateService: StateService, - activeAccount: ActiveAccountService, collectionService: CollectionService, + auditService: AuditService, stateService: StateService, collectionService: CollectionService, messagingService: MessagingService, private route: ActivatedRoute, private router: Router, private location: Location, eventService: EventService, policyService: PolicyService, - private popupUtilsService: PopupUtilsService, organizationService: OrganizationService) { + private popupUtilsService: PopupUtilsService, organizationService: OrganizationService, + passwordRepromptService: PasswordRepromptService, logService: LogService) { super(cipherService, folderService, i18nService, platformUtilsService, auditService, stateService, collectionService, messagingService, - eventService, policyService, activeAccount, organizationService); + eventService, policyService, logService, passwordRepromptService, organizationService); } async ngOnInit() { @@ -117,7 +117,7 @@ export class AddEditComponent extends BaseAddEditComponent { async load() { await super.load(); this.showAutoFillOnPageLoadOptions = this.cipher.type === CipherType.Login && - await this.activeAccount.getInformation(StorageKey.EnableAutoFillOnPageLoad); + await this.stateService.getEnableAutoFillOnPageLoad(); } async submit(): Promise { @@ -161,7 +161,7 @@ export class AddEditComponent extends BaseAddEditComponent { async generatePassword(): Promise { const confirmed = await super.generatePassword(); if (confirmed) { - this.stateService.save('addEditCipherInfo', { + this.stateService.setAddEditCipherInfo({ cipher: this.cipher, collectionIds: this.collections == null ? [] : this.collections.filter(c => (c as any).checked).map(c => c.id), diff --git a/src/popup/vault/attachments.component.ts b/src/popup/vault/attachments.component.ts index 6760b99240..85b48d4060 100644 --- a/src/popup/vault/attachments.component.ts +++ b/src/popup/vault/attachments.component.ts @@ -2,7 +2,6 @@ import { Location } from '@angular/common'; import { Component } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { ApiService } from 'jslib-common/abstractions/api.service'; import { CipherService } from 'jslib-common/abstractions/cipher.service'; import { CryptoService } from 'jslib-common/abstractions/crypto.service'; @@ -10,6 +9,8 @@ import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { AttachmentsComponent as BaseAttachmentsComponent } from 'jslib-angular/components/attachments.component'; +import { StateService } from 'jslib-common/abstractions/state.service'; +import { LogService } from 'jslib-common/abstractions/log.service'; @Component({ selector: 'app-vault-attachments', @@ -21,9 +22,9 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { constructor(cipherService: CipherService, i18nService: I18nService, cryptoService: CryptoService, platformUtilsService: PlatformUtilsService, apiService: ApiService, private location: Location, - private route: ActivatedRoute, activeAccount: ActiveAccountService) { + private route: ActivatedRoute, stateService: StateService, logService: LogService) { super(cipherService, i18nService, cryptoService, platformUtilsService, - apiService, window, activeAccount); + apiService, window, logService, stateService); } async ngOnInit() { diff --git a/src/popup/vault/ciphers.component.ts b/src/popup/vault/ciphers.component.ts index 1c221bb299..ac6baa34f9 100644 --- a/src/popup/vault/ciphers.component.ts +++ b/src/popup/vault/ciphers.component.ts @@ -34,6 +34,7 @@ import { BroadcasterService } from 'jslib-angular/services/broadcaster.service'; import { CiphersComponent as BaseCiphersComponent } from 'jslib-angular/components/ciphers.component'; import { PopupUtilsService } from '../services/popup-utils.service'; +import { BrowserComponentState } from 'jslib-common/models/domain/browserComponentState'; const ComponentId = 'CiphersComponent'; @@ -43,7 +44,7 @@ const ComponentId = 'CiphersComponent'; }) export class CiphersComponent extends BaseCiphersComponent implements OnInit, OnDestroy { groupingTitle: string; - state: any; + state: BrowserComponentState; folderId: string = null; collectionId: string = null; type: CipherType = null; @@ -72,7 +73,7 @@ export class CiphersComponent extends BaseCiphersComponent implements OnInit, On this.searchTypeSearch = !this.platformUtilsService.isSafari(); const queryParamsSub = this.route.queryParams.subscribe(async params => { if (this.applySavedState) { - this.state = (await this.stateService.get(ComponentId)) || {}; + this.state = await this.stateService.getBrowserCipherComponentState(); if (this.state.searchText) { this.searchText = this.state.searchText; } @@ -135,7 +136,7 @@ export class CiphersComponent extends BaseCiphersComponent implements OnInit, On window.setTimeout(() => this.popupUtils.setContentScrollY(window, this.state.scrollY, this.scrollingContainer), 0); } - this.stateService.remove(ComponentId); + this.stateService.setBrowserCipherComponentState(null); if (queryParamsSub != null) { queryParamsSub.unsubscribe(); } @@ -231,6 +232,6 @@ export class CiphersComponent extends BaseCiphersComponent implements OnInit, On scrollY: this.popupUtils.getContentScrollY(window, this.scrollingContainer), searchText: this.searchText, }; - await this.stateService.save(ComponentId, this.state); + await this.stateService.setBrowserCipherComponentState(this.state); } } diff --git a/src/popup/vault/collections.component.ts b/src/popup/vault/collections.component.ts index 476d8d7f82..30bb7ef141 100644 --- a/src/popup/vault/collections.component.ts +++ b/src/popup/vault/collections.component.ts @@ -8,6 +8,7 @@ import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { CollectionsComponent as BaseCollectionsComponent } from 'jslib-angular/components/collections.component'; +import { LogService } from 'jslib-common/abstractions/log.service'; @Component({ selector: 'app-vault-collections', @@ -16,8 +17,8 @@ import { CollectionsComponent as BaseCollectionsComponent } from 'jslib-angular/ export class CollectionsComponent extends BaseCollectionsComponent { constructor(collectionService: CollectionService, platformUtilsService: PlatformUtilsService, i18nService: I18nService, cipherService: CipherService, - private route: ActivatedRoute, private location: Location) { - super(collectionService, platformUtilsService, i18nService, cipherService); + private route: ActivatedRoute, private location: Location, logService: LogService) { + super(collectionService, platformUtilsService, i18nService, cipherService, logService); } async ngOnInit() { diff --git a/src/popup/vault/current-tab.component.ts b/src/popup/vault/current-tab.component.ts index 9a0aa89c18..74003dfd6f 100644 --- a/src/popup/vault/current-tab.component.ts +++ b/src/popup/vault/current-tab.component.ts @@ -16,11 +16,9 @@ import { BroadcasterService } from 'jslib-angular/services/broadcaster.service'; import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType'; import { CipherType } from 'jslib-common/enums/cipherType'; -import { StorageKey } from 'jslib-common/enums/storageKey'; import { CipherView } from 'jslib-common/models/view/cipherView'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { CipherService } from 'jslib-common/abstractions/cipher.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { PasswordRepromptService } from 'jslib-common/abstractions/passwordReprompt.service'; @@ -33,6 +31,7 @@ import { AutofillService } from '../../services/abstractions/autofill.service'; import { PopupUtilsService } from '../services/popup-utils.service'; import { Utils } from 'jslib-common/misc/utils'; +import { StateService } from 'jslib-common/abstractions/state.service'; const BroadcasterSubscriptionId = 'CurrentTabComponent'; @@ -62,7 +61,7 @@ export class CurrentTabComponent implements OnInit, OnDestroy { private toasterService: ToasterService, private i18nService: I18nService, private router: Router, private ngZone: NgZone, private broadcasterService: BroadcasterService, private changeDetectorRef: ChangeDetectorRef, private syncService: SyncService, - private searchService: SearchService, private activeAccount: ActiveAccountService, + private searchService: SearchService, private stateService: StateService, private passwordRepromptService: PasswordRepromptService) { } @@ -208,9 +207,8 @@ export class CurrentTabComponent implements OnInit, OnDestroy { }); const otherTypes: CipherType[] = []; - const dontShowCards = await this.activeAccount.getInformation(StorageKey.DontShowCardsCurrentTab); - const dontShowIdentities = await this.activeAccount.getInformation( - StorageKey.DontShowIdentitiesCurrentTab); + const dontShowCards = await this.stateService.getDontShowCardsCurrentTab(); + const dontShowIdentities = await this.stateService.getDontShowIdentitiesCurrentTab(); if (!dontShowCards) { otherTypes.push(CipherType.Card); } diff --git a/src/popup/vault/groupings.component.ts b/src/popup/vault/groupings.component.ts index 2a6bbd7be3..080d4b0fc0 100644 --- a/src/popup/vault/groupings.component.ts +++ b/src/popup/vault/groupings.component.ts @@ -19,7 +19,6 @@ import { CipherView } from 'jslib-common/models/view/cipherView'; import { CollectionView } from 'jslib-common/models/view/collectionView'; import { FolderView } from 'jslib-common/models/view/folderView'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { CipherService } from 'jslib-common/abstractions/cipher.service'; import { CollectionService } from 'jslib-common/abstractions/collection.service'; import { FolderService } from 'jslib-common/abstractions/folder.service'; @@ -78,18 +77,17 @@ export class GroupingsComponent extends BaseGroupingsComponent implements OnInit private cipherService: CipherService, private router: Router, private ngZone: NgZone, private broadcasterService: BroadcasterService, private changeDetectorRef: ChangeDetectorRef, private route: ActivatedRoute, - private stateService: StateService, private popupUtils: PopupUtilsService, + stateService: StateService, private popupUtils: PopupUtilsService, private syncService: SyncService, private platformUtilsService: PlatformUtilsService, - private searchService: SearchService, private location: Location, - activeAccount: ActiveAccountService) { - super(collectionService, folderService, activeAccount); + private searchService: SearchService, private location: Location) { + super(collectionService, folderService, stateService); this.noFolderListSize = 100; } async ngOnInit() { this.searchTypeSearch = !this.platformUtilsService.isSafari(); this.showLeftHeader = !(this.popupUtils.inSidebar(window) && this.platformUtilsService.isFirefox()); - this.stateService.remove('CiphersComponent'); + this.stateService.setBrowserCipherComponentState(null); this.broadcasterService.subscribe(ComponentId, (message: any) => { this.ngZone.run(async () => { @@ -109,7 +107,7 @@ export class GroupingsComponent extends BaseGroupingsComponent implements OnInit const restoredScopeState = await this.restoreState(); const queryParamsSub = this.route.queryParams.subscribe(async params => { - this.state = (await this.stateService.get(ComponentId)) || {}; + this.state = (await this.stateService.getBrowserGroupingComponentState()) || {}; if (this.state.searchText) { this.searchText = this.state.searchText; } else if (params.searchText) { @@ -297,7 +295,7 @@ export class GroupingsComponent extends BaseGroupingsComponent implements OnInit closeOnEsc(e: KeyboardEvent) { // If input not empty, use browser default behavior of clearing input instead - if (e.key === 'Escape' && (this.searchText == null || this.searchText === '')) { + if (e.key === 'Escape' && (this.searchText == null || this.searchText === '')) { BrowserApi.closePopup(window); } } @@ -306,10 +304,6 @@ export class GroupingsComponent extends BaseGroupingsComponent implements OnInit this.state = { scrollY: this.popupUtils.getContentScrollY(window), searchText: this.searchText, - }; - await this.stateService.save(ComponentId, this.state); - - this.scopeState = { favoriteCiphers: this.favoriteCiphers, noFolderCiphers: this.noFolderCiphers, ciphers: this.ciphers, @@ -320,11 +314,11 @@ export class GroupingsComponent extends BaseGroupingsComponent implements OnInit collections: this.collections, deletedCount: this.deletedCount, }; - await this.stateService.save(ScopeStateId, this.scopeState); + await this.stateService.setBrowserGroupingComponentState(this.scopeState); } private async restoreState(): Promise { - this.scopeState = await this.stateService.get(ScopeStateId); + this.scopeState = await this.stateService.getBrowserGroupingComponentState(); if (this.scopeState == null) { return false; } diff --git a/src/popup/vault/share.component.ts b/src/popup/vault/share.component.ts index 4035440a76..2e4afc7048 100644 --- a/src/popup/vault/share.component.ts +++ b/src/popup/vault/share.component.ts @@ -4,7 +4,6 @@ import { Router, } from '@angular/router'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { CipherService } from 'jslib-common/abstractions/cipher.service'; import { CollectionService } from 'jslib-common/abstractions/collection.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; @@ -12,6 +11,7 @@ import { OrganizationService } from 'jslib-common/abstractions/organization.serv import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { ShareComponent as BaseShareComponent } from 'jslib-angular/components/share.component'; +import { LogService } from 'jslib-common/abstractions/log.service'; @Component({ selector: 'app-vault-share', @@ -19,11 +19,11 @@ import { ShareComponent as BaseShareComponent } from 'jslib-angular/components/s }) export class ShareComponent extends BaseShareComponent { constructor(collectionService: CollectionService, platformUtilsService: PlatformUtilsService, - i18nService: I18nService, activeAccount: ActiveAccountService, + i18nService: I18nService, logService: LogService, cipherService: CipherService, private route: ActivatedRoute, private router: Router, organizationService: OrganizationService) { super(collectionService, platformUtilsService, i18nService, cipherService, - activeAccount, organizationService); + logService, organizationService); } async ngOnInit() { diff --git a/src/popup/vault/view.component.ts b/src/popup/vault/view.component.ts index cd1950da37..22726a375f 100644 --- a/src/popup/vault/view.component.ts +++ b/src/popup/vault/view.component.ts @@ -9,7 +9,6 @@ import { Router, } from '@angular/router'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { ApiService } from 'jslib-common/abstractions/api.service'; import { AuditService } from 'jslib-common/abstractions/audit.service'; import { CipherService } from 'jslib-common/abstractions/cipher.service'; @@ -33,6 +32,8 @@ import { ViewComponent as BaseViewComponent } from 'jslib-angular/components/vie import { BrowserApi } from '../../browser/browserApi'; import { AutofillService } from '../../services/abstractions/autofill.service'; import { PopupUtilsService } from '../services/popup-utils.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; +import { LogService } from 'jslib-common/abstractions/log.service'; const BroadcasterSubscriptionId = 'ChildViewComponent'; @@ -54,14 +55,15 @@ export class ViewComponent extends BaseViewComponent { auditService: AuditService, private route: ActivatedRoute, private router: Router, private location: Location, broadcasterService: BroadcasterService, ngZone: NgZone, - changeDetectorRef: ChangeDetectorRef, activeAccount: ActiveAccountService, + changeDetectorRef: ChangeDetectorRef, stateService: StateService, eventService: EventService, private autofillService: AutofillService, private messagingService: MessagingService, private popupUtilsService: PopupUtilsService, - apiService: ApiService, passwordRepromptService: PasswordRepromptService) { + apiService: ApiService, passwordRepromptService: PasswordRepromptService, + logService: LogService) { super(cipherService, totpService, tokenService, i18nService, cryptoService, platformUtilsService, auditService, window, broadcasterService, ngZone, changeDetectorRef, eventService, - apiService, passwordRepromptService, activeAccount); + apiService, passwordRepromptService, logService, stateService); } ngOnInit() { diff --git a/src/services/autofill.service.ts b/src/services/autofill.service.ts index 6675b86100..c34068d703 100644 --- a/src/services/autofill.service.ts +++ b/src/services/autofill.service.ts @@ -1,4 +1,3 @@ -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { CipherService } from 'jslib-common/abstractions/cipher.service'; import { EventService } from 'jslib-common/abstractions/event.service'; import { TotpService } from 'jslib-common/abstractions/totp.service'; @@ -17,6 +16,7 @@ import AutofillPageDetails from '../models/autofillPageDetails'; import AutofillScript from '../models/autofillScript'; import { BrowserApi } from '../browser/browserApi'; +import { StateService } from 'jslib-common/abstractions/state.service'; const CardAttributes: string[] = ['autoCompleteType', 'data-stripe', 'htmlName', 'htmlID', 'label-tag', 'placeholder', 'label-left', 'label-top', 'data-recurly']; @@ -130,7 +130,7 @@ var IsoProvinces: { [id: string]: string; } = { export default class AutofillService implements AutofillServiceInterface { - constructor(private cipherService: CipherService, private activeAccount: ActiveAccountService, + constructor(private cipherService: CipherService, private stateService: StateService, private totpService: TotpService, private eventService: EventService) { } getFormsWithPasswordFields(pageDetails: AutofillPageDetails): any[] { @@ -172,7 +172,7 @@ export default class AutofillService implements AutofillServiceInterface { throw new Error('Nothing to auto-fill.'); } - const canAccessPremium = this.activeAccount.canAccessPremium; + const canAccessPremium = await this.stateService.getCanAccessPremium(); let didAutofill = false; options.pageDetails.forEach((pd: any) => { // make sure we're still on correct tab diff --git a/src/services/browserCrypto.service.ts b/src/services/browserCrypto.service.ts index ab640d284b..b9bb4d0585 100644 --- a/src/services/browserCrypto.service.ts +++ b/src/services/browserCrypto.service.ts @@ -1,4 +1,4 @@ -import { KeySuffixOptions } from 'jslib-common/models/domain/settingStorageOptions'; +import { KeySuffixOptions } from 'jslib-common/enums/keySuffixOptions'; import { CryptoService } from 'jslib-common/services/crypto.service'; diff --git a/src/services/browserPlatformUtils.service.ts b/src/services/browserPlatformUtils.service.ts index 2f7d4eafcc..4cd68581bf 100644 --- a/src/services/browserPlatformUtils.service.ts +++ b/src/services/browserPlatformUtils.service.ts @@ -4,10 +4,9 @@ import { SafariApp } from '../browser/safariApp'; import { DeviceType } from 'jslib-common/enums/deviceType'; import { ThemeType } from 'jslib-common/enums/themeType'; -import { ActiveAccountService } from 'jslib-common/abstractions/activeAccount.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; -import { StorageKey } from 'jslib-common/enums/storageKey'; +import { StateService } from 'jslib-common/abstractions/state.service'; const DialogPromiseExpiration = 600000; // 10 minutes @@ -19,7 +18,7 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService private deviceCache: DeviceType = null; private prefersColorSchemeDark = window.matchMedia('(prefers-color-scheme: dark)'); - constructor(private messagingService: MessagingService, private activeAccount: ActiveAccountService, + constructor(private messagingService: MessagingService, private stateService: StateService, private clipboardWriteCallback: (clipboardValue: string, clearMs: number) => void, private biometricCallback: () => Promise) { } @@ -119,7 +118,7 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService } supportsWebAuthn(win: Window): boolean { - return (typeof(PublicKeyCredential) !== 'undefined'); + return (typeof (PublicKeyCredential) !== 'undefined'); } supportsDuo(): boolean { @@ -331,7 +330,7 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService } async getEffectiveTheme() { - const theme = await this.activeAccount.getInformation(StorageKey.Theme); + const theme = await this.stateService.getTheme() as ThemeType; if (theme == null || theme === ThemeType.System) { return this.getDefaultSystemTheme(); } else { diff --git a/src/services/browserStorage.service.ts b/src/services/browserStorage.service.ts index 0f417ae223..3d2c003215 100644 --- a/src/services/browserStorage.service.ts +++ b/src/services/browserStorage.service.ts @@ -26,11 +26,7 @@ export default class BrowserStorageService implements StorageService { async save(key: string, obj: any): Promise { if (obj == null) { // Fix safari not liking null in set - return new Promise(resolve => { - this.chromeStorageApi.remove(key, () => { - resolve(); - }); - }); + return this.remove(key); } if (obj instanceof Set) {