diff --git a/common/src/enums/htmlStorageLocation.ts b/common/src/enums/htmlStorageLocation.ts
new file mode 100644
index 00000000..59560c36
--- /dev/null
+++ b/common/src/enums/htmlStorageLocation.ts
@@ -0,0 +1,5 @@
+export enum HtmlStorageLocation {
+ Local = 'local',
+ Memory = 'memory',
+ Session = 'session',
+}
diff --git a/common/src/models/domain/globals.ts b/common/src/models/domain/globals.ts
index 7ba42cb9..4828b3ce 100644
--- a/common/src/models/domain/globals.ts
+++ b/common/src/models/domain/globals.ts
@@ -12,7 +12,8 @@ export class Globals {
window: Map = new Map();
twoFactorToken: string;
disableFavicon: boolean;
-
biometricAwaitingAcceptance: boolean;
biometricFingerprintValidated: boolean;
+ vaultTimeout: number;
+ vaultTimeoutAction: string;
}
diff --git a/common/src/models/domain/storageOptions.ts b/common/src/models/domain/storageOptions.ts
index d4537a12..e4fc4b35 100644
--- a/common/src/models/domain/storageOptions.ts
+++ b/common/src/models/domain/storageOptions.ts
@@ -1,3 +1,4 @@
+import { HtmlStorageLocation } from '../../enums/htmlStorageLocation';
import { KeySuffixOptions } from '../../enums/keySuffixOptions';
import { StorageLocation } from '../../enums/storageLocation';
@@ -6,4 +7,5 @@ export type StorageOptions = {
storageLocation?: StorageLocation;
useSecureStorage?: boolean;
userId?: string;
+ htmlStorageLocation?: HtmlStorageLocation;
};
diff --git a/common/src/services/state.service.ts b/common/src/services/state.service.ts
index 064df1a3..187098c7 100644
--- a/common/src/services/state.service.ts
+++ b/common/src/services/state.service.ts
@@ -5,6 +5,7 @@ import { Account, AuthenticationStatus } from '../models/domain/account';
import { LogService } from '../abstractions/log.service';
import { StorageService } from '../abstractions/storage.service';
+import { HtmlStorageLocation } from '../enums/htmlStorageLocation';
import { KdfType } from '../enums/kdfType';
import { StorageLocation } from '../enums/storageLocation';
import { UriMatchType } from '../enums/uriMatchType';
@@ -42,7 +43,15 @@ export class StateService implements StateServiceAbstraction {
}
private get defaultOnDiskOptions(): StorageOptions {
- return { storageLocation: StorageLocation.Disk, userId: this.state.activeUserId };
+ return { storageLocation: StorageLocation.Disk, htmlStorageLocation: HtmlStorageLocation.Session, userId: this.state.activeUserId };
+ }
+
+ private get defaultOnDiskLocalOptions(): StorageOptions {
+ return { storageLocation: StorageLocation.Disk, htmlStorageLocation: HtmlStorageLocation.Local, userId: this.state.activeUserId };
+ }
+
+ private get defaultOnDiskMemoryOptions(): StorageOptions {
+ return { storageLocation: StorageLocation.Disk, htmlStorageLocation: HtmlStorageLocation.Memory, userId: this.state.activeUserId };
}
private get defaultSecureStorageOptions(): StorageOptions {
@@ -60,7 +69,7 @@ export class StateService implements StateServiceAbstraction {
}
async getEnableGravitars(options?: StorageOptions): Promise {
- return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions))).enableGravitars ?? true;
+ return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskLocalOptions))).enableGravitars ?? true;
}
async getAddEditCipherInfo(options?: StorageOptions): Promise {
@@ -128,7 +137,7 @@ export class StateService implements StateServiceAbstraction {
}
async getEncryptedCiphers(options?: StorageOptions): Promise<{ [id: string]: CipherData }> {
- return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.encryptedCiphers;
+ return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskMemoryOptions)))?.encryptedCiphers;
}
async getDecryptedCiphers(options?: StorageOptions): Promise {
@@ -144,7 +153,7 @@ export class StateService implements StateServiceAbstraction {
}
async getEncryptedCollections(options?: StorageOptions): Promise<{ [id: string]: CollectionData }> {
- return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.encryptedCollections;
+ return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskMemoryOptions)))?.encryptedCollections;
}
async getDecryptedCollections(options?: StorageOptions): Promise {
@@ -204,7 +213,7 @@ export class StateService implements StateServiceAbstraction {
}
async getDisableFavicon(options?: StorageOptions): Promise {
- return (await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.disableFavicon ?? false;
+ return (await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskLocalOptions)))?.disableFavicon ?? false;
}
async getDisableGa(options?: StorageOptions): Promise {
@@ -307,7 +316,7 @@ export class StateService implements StateServiceAbstraction {
}
async getEncryptedFolders(options?: StorageOptions): Promise<{ [id: string]: FolderData }> {
- return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.encryptedFolders;
+ return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskMemoryOptions)))?.encryptedFolders;
}
async getDecryptedFolders(options?: StorageOptions): Promise {
@@ -335,7 +344,7 @@ export class StateService implements StateServiceAbstraction {
}
async getLastSync(options?: StorageOptions): Promise {
- return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions)))?.lastSync;
+ return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskMemoryOptions)))?.lastSync;
}
async getLastActive(options?: StorageOptions): Promise {
@@ -428,11 +437,11 @@ export class StateService implements StateServiceAbstraction {
}
async getRememberEmail(options?: StorageOptions): Promise {
- return (await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.rememberEmail ?? false;
+ return (await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskLocalOptions)))?.rememberEmail ?? false;
}
async getRememberedEmail(options?: StorageOptions): Promise {
- return (await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.rememberedEmail;
+ return (await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskLocalOptions)))?.rememberedEmail;
}
async getSecurityStamp(options?: StorageOptions): Promise {
@@ -440,7 +449,7 @@ export class StateService implements StateServiceAbstraction {
}
async getEncryptedSends(options?: StorageOptions): Promise<{ [id: string]: SendData }> {
- return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.encryptedSends;
+ return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskMemoryOptions)))?.encryptedSends;
}
async getDecryptedSends(options?: StorageOptions): Promise {
@@ -448,7 +457,7 @@ export class StateService implements StateServiceAbstraction {
}
async getSettings(options?: StorageOptions): Promise {
- return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.settings;
+ return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskMemoryOptions)))?.settings;
}
async getSsoCodeVerifier(options?: StorageOptions): Promise {
@@ -456,7 +465,7 @@ export class StateService implements StateServiceAbstraction {
}
async getSsoOrgIdentifier(options?: StorageOptions): Promise {
- return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions)))?.ssoOrganizationIdentifier;
+ return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskLocalOptions)))?.ssoOrganizationIdentifier;
}
async getSsoState(options?: StorageOptions): Promise {
@@ -464,21 +473,25 @@ export class StateService implements StateServiceAbstraction {
}
async getTheme(options?: StorageOptions): Promise {
- let theme = (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.theme;
- theme = theme ?? (await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.theme;
- return theme;
+ const accountTheme = (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskLocalOptions)))?.theme;
+ const globalTheme = (await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskLocalOptions)))?.theme;
+ return accountTheme ?? globalTheme;
}
async getTwoFactorToken(options?: StorageOptions): Promise {
- return (await this.getGlobals(this.reconcileOptions(options, this.defaultInMemoryOptions)))?.twoFactorToken;
+ return (await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskLocalOptions)))?.twoFactorToken;
}
async getVaultTimeout(options?: StorageOptions): Promise {
- return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.vaultTimeout;
+ const accountVaultTimeout = (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.vaultTimeout;
+ const globalVaultTimeout = (await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.vaultTimeout;
+ return accountVaultTimeout ?? globalVaultTimeout;
}
async getVaultTimeoutAction(options?: StorageOptions): Promise {
- return (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.vaultTimeoutAction;
+ const accountVaultTimeoutAction = (await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.vaultTimeoutAction;
+ const globalVaultTimeoutAction = (await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskOptions)))?.vaultTimeoutAction;
+ return accountVaultTimeoutAction ?? globalVaultTimeoutAction;
}
async getOrganizations(options?: StorageOptions): Promise<{ [id: string]: OrganizationData }> {
@@ -571,9 +584,9 @@ export class StateService implements StateServiceAbstraction {
}
async setEncryptedCiphers(value: { [id: string]: CipherData }, options?: StorageOptions): Promise {
- const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions));
+ const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskMemoryOptions));
account.encryptedCiphers = value;
- await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskOptions));
+ await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskMemoryOptions));
}
async setDecryptedCiphers(value: CipherView[], options?: StorageOptions): Promise {
@@ -595,9 +608,9 @@ export class StateService implements StateServiceAbstraction {
}
async setEncryptedCollections(value: { [id: string]: CollectionData }, options?: StorageOptions): Promise {
- const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions));
+ const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskMemoryOptions));
account.encryptedCollections = value;
- await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskOptions));
+ await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskMemoryOptions));
}
async setDecryptedCollections(value: CollectionView[], options?: StorageOptions): Promise {
@@ -830,9 +843,9 @@ export class StateService implements StateServiceAbstraction {
}
async setEncryptedFolders(value: { [id: string]: FolderData }, options?: StorageOptions): Promise {
- const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions));
+ const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskMemoryOptions));
account.encryptedFolders = value;
- await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskOptions));
+ await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskMemoryOptions));
}
async setDecryptedFolders(value: FolderView[], options?: StorageOptions): Promise {
@@ -872,9 +885,9 @@ export class StateService implements StateServiceAbstraction {
}
async setLastSync(value: string, options?: StorageOptions): Promise {
- const account = await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions));
+ const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskMemoryOptions));
account.lastSync = value;
- await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions));
+ await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskMemoryOptions));
}
async setLastActive(value: number, options?: StorageOptions): Promise {
@@ -1040,9 +1053,9 @@ export class StateService implements StateServiceAbstraction {
}
async setEncryptedSends(value: { [id: string]: SendData }, options?: StorageOptions): Promise {
- const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions));
+ const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskMemoryOptions));
account.encryptedSends = value;
- await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskOptions));
+ await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskMemoryOptions));
}
async setDecryptedSends(value: SendView[], options?: StorageOptions): Promise {
@@ -1052,9 +1065,9 @@ export class StateService implements StateServiceAbstraction {
}
async setSettings(value: any, options?: StorageOptions): Promise {
- const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions));
+ const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskMemoryOptions));
account.settings = value;
- await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskOptions));
+ await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskMemoryOptions));
}
async setSsoCodeVerifier(value: string, options?: StorageOptions): Promise {
@@ -1064,9 +1077,9 @@ export class StateService implements StateServiceAbstraction {
}
async setSsoOrganizationIdentifier(value: string, options?: StorageOptions): Promise {
- const account = await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions));
+ const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskLocalOptions));
account.ssoOrganizationIdentifier = value;
- await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions));
+ await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskLocalOptions));
}
async setSsoState(value: string, options?: StorageOptions): Promise {
@@ -1076,21 +1089,21 @@ export class StateService implements StateServiceAbstraction {
}
async setTheme(value: string, options?: StorageOptions): Promise {
- const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskOptions));
+ const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskLocalOptions));
if (account != null) {
account.theme = value;
- await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskOptions));
+ await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskLocalOptions));
}
- const globals = await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskOptions));
+ const globals = await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskLocalOptions));
globals.theme = value;
- await this.saveGlobals(globals, this.reconcileOptions(options, this.defaultOnDiskOptions));
+ await this.saveGlobals(globals, this.reconcileOptions(options, this.defaultOnDiskLocalOptions));
}
async setTwoFactorToken(value: string, options?: StorageOptions): Promise {
- const globals = await this.getGlobals(this.reconcileOptions(options, this.defaultInMemoryOptions));
+ const globals = await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskLocalOptions));
globals.twoFactorToken = value;
- await this.saveGlobals(globals, this.reconcileOptions(options, this.defaultInMemoryOptions));
+ await this.saveGlobals(globals, this.reconcileOptions(options, this.defaultOnDiskLocalOptions));
}
async setVaultTimeout(value: number, options?: StorageOptions): Promise {
@@ -1118,9 +1131,9 @@ export class StateService implements StateServiceAbstraction {
}
async setEnableGravitars(value: boolean, options?: StorageOptions): Promise {
- const account = await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions));
+ const account = await this.getAccount(this.reconcileOptions(options, this.defaultOnDiskLocalOptions));
account.enableGravitars = value;
- await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions));
+ await this.saveAccount(account, this.reconcileOptions(options, this.defaultOnDiskLocalOptions));
}
async setAddEditCipherInfo(value: any, options?: StorageOptions): Promise {
@@ -1130,9 +1143,9 @@ export class StateService implements StateServiceAbstraction {
}
async setRememberedEmail(value: string, options?: StorageOptions): Promise {
- const globals = await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskOptions));
+ const globals = await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskLocalOptions));
globals.rememberedEmail = value;
- await this.saveGlobals(globals, this.reconcileOptions(options, this.defaultOnDiskOptions));
+ await this.saveGlobals(globals, this.reconcileOptions(options, this.defaultOnDiskLocalOptions));
}
async setOrganizationInvitation(value: any, options?: StorageOptions): Promise {
@@ -1149,10 +1162,10 @@ export class StateService implements StateServiceAbstraction {
await this.pushAccounts();
}
- async setWindow(value: Map): Promise {
- const globals = await this.getGlobals({ storageLocation: StorageLocation.Disk });
+ async setWindow(value: Map, options?: StorageOptions): Promise {
+ const globals = await this.getGlobals(this.reconcileOptions(options, this.defaultOnDiskOptions));
globals.window = value;
- return await this.saveGlobals(globals, { storageLocation: StorageLocation.Disk });
+ return await this.saveGlobals(globals, this.reconcileOptions(options, this.defaultOnDiskOptions));
}
async purge(options?: StorageOptions): Promise {
@@ -1198,9 +1211,9 @@ export class StateService implements StateServiceAbstraction {
private async saveGlobalsToDisk(globals: Globals, options: StorageOptions): Promise {
if (options.useSecureStorage) {
- await this.secureStorageService.save('globals', globals);
+ await this.secureStorageService.save('globals', globals, options);
} else {
- await this.storageService.save('globals', globals);
+ await this.storageService.save('globals', globals, options);
}
}
@@ -1270,9 +1283,9 @@ export class StateService implements StateServiceAbstraction {
private async saveAccountToDisk(account: Account, options: StorageOptions): Promise {
if (options.useSecureStorage) {
- await this.secureStorageService.save(account.userId, account);
+ await this.secureStorageService.save(account.userId, account, options);
} else {
- await this.storageService.save(account.userId, account);
+ await this.storageService.save(account.userId, account, options);
}
await this.pushAccounts();
}
@@ -1332,6 +1345,7 @@ export class StateService implements StateServiceAbstraction {
requestedOptions.storageLocation = requestedOptions?.storageLocation ?? defaultOptions.storageLocation;
requestedOptions.keySuffix = requestedOptions?.keySuffix ?? defaultOptions.keySuffix;
requestedOptions.useSecureStorage = requestedOptions?.useSecureStorage ?? defaultOptions.useSecureStorage;
+ requestedOptions.htmlStorageLocation = requestedOptions?.htmlStorageLocation ?? defaultOptions.htmlStorageLocation;
return requestedOptions;
}
}