1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 08:13:42 +00:00

share disk cache to fix syncing issues between contexts

This commit is contained in:
Jacob Fink
2023-06-16 11:46:10 -04:00
parent c5384cd5f2
commit 7f0749ca5c
4 changed files with 25 additions and 14 deletions

View File

@@ -1,4 +1,4 @@
import { BehaviorSubject } from "rxjs"; import { BehaviorSubject, Observable } from "rxjs";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { StateMigrationService } from "@bitwarden/common/platform/abstractions/state-migration.service"; import { StateMigrationService } from "@bitwarden/common/platform/abstractions/state-migration.service";
@@ -33,11 +33,6 @@ export class BrowserStateService
protected activeAccountSubject: BehaviorSubject<string>; protected activeAccountSubject: BehaviorSubject<string>;
@sessionSync({ initializer: (b: boolean) => b }) @sessionSync({ initializer: (b: boolean) => b })
protected activeAccountUnlockedSubject: BehaviorSubject<boolean>; protected activeAccountUnlockedSubject: BehaviorSubject<boolean>;
@sessionSync({
initializer: Account.fromJSON as any, // TODO: Remove this any when all any types are removed from Account
initializeAs: "record",
})
protected accountDiskCache: BehaviorSubject<Record<string, Account>>;
protected accountDeserializer = Account.fromJSON; protected accountDeserializer = Account.fromJSON;
@@ -48,7 +43,8 @@ export class BrowserStateService
logService: LogService, logService: LogService,
stateMigrationService: StateMigrationService, stateMigrationService: StateMigrationService,
stateFactory: StateFactory<GlobalState, Account>, stateFactory: StateFactory<GlobalState, Account>,
useAccountCache = false useAccountCache = true,
accountCache: Observable<Record<string, Account>> = null
) { ) {
super( super(
storageService, storageService,
@@ -59,6 +55,12 @@ export class BrowserStateService
stateFactory, stateFactory,
useAccountCache useAccountCache
); );
// Hack to allow shared disk cache between contexts on browser
// TODO: Remove when services are consolidated to a single context
if (useAccountCache && accountCache) {
accountCache.subscribe(this.accountDiskCacheSubject);
}
} }
async addAccount(account: Account) { async addAccount(account: Account) {

View File

@@ -440,13 +440,20 @@ function getBgService<T>(service: keyof MainBackground) {
logService: LogServiceAbstraction, logService: LogServiceAbstraction,
stateMigrationService: StateMigrationService stateMigrationService: StateMigrationService
) => { ) => {
// hack to share the disk cache between the two contexts.
// TODO: we need to figure out a better way of sharing/syncing
// the disk cache
const bgStateService = getBgService<StateServiceAbstraction>("stateService");
const bgDiskCache = bgStateService().accountDiskCache$;
return new BrowserStateService( return new BrowserStateService(
storageService, storageService,
secureStorageService, secureStorageService,
memoryStorageService, memoryStorageService,
logService, logService,
stateMigrationService, stateMigrationService,
new StateFactory(GlobalState, Account) new StateFactory(GlobalState, Account),
true,
bgDiskCache
); );
}, },
deps: [ deps: [

View File

@@ -37,6 +37,7 @@ export abstract class StateService<T extends Account = Account> {
accounts$: Observable<{ [userId: string]: T }>; accounts$: Observable<{ [userId: string]: T }>;
activeAccount$: Observable<string>; activeAccount$: Observable<string>;
activeAccountUnlocked$: Observable<boolean>; activeAccountUnlocked$: Observable<boolean>;
accountDiskCache$: Observable<Record<string, T>>;
addAccount: (account: T) => Promise<void>; addAccount: (account: T) => Promise<void>;
setActiveUser: (userId: string) => Promise<void>; setActiveUser: (userId: string) => Promise<void>;

View File

@@ -95,7 +95,8 @@ export class StateService<
private hasBeenInited = false; private hasBeenInited = false;
private isRecoveredSession = false; private isRecoveredSession = false;
protected accountDiskCache = new BehaviorSubject<Record<string, TAccount>>({}); protected accountDiskCacheSubject = new BehaviorSubject<Record<string, TAccount>>({});
accountDiskCache$ = this.accountDiskCacheSubject.asObservable();
// default account serializer, must be overridden by child class // default account serializer, must be overridden by child class
protected accountDeserializer = Account.fromJSON as (json: Jsonify<TAccount>) => TAccount; protected accountDeserializer = Account.fromJSON as (json: Jsonify<TAccount>) => TAccount;
@@ -2770,7 +2771,7 @@ export class StateService<
} }
if (this.useAccountCache) { if (this.useAccountCache) {
const cachedAccount = this.accountDiskCache.value[options.userId]; const cachedAccount = this.accountDiskCacheSubject.value[options.userId];
if (cachedAccount != null) { if (cachedAccount != null) {
return cachedAccount; return cachedAccount;
} }
@@ -3166,15 +3167,15 @@ export class StateService<
private setDiskCache(key: string, value: TAccount, options?: StorageOptions) { private setDiskCache(key: string, value: TAccount, options?: StorageOptions) {
if (this.useAccountCache) { if (this.useAccountCache) {
this.accountDiskCache.value[key] = value; this.accountDiskCacheSubject.value[key] = value;
this.accountDiskCache.next(this.accountDiskCache.value); this.accountDiskCacheSubject.next(this.accountDiskCacheSubject.value);
} }
} }
private deleteDiskCache(key: string) { private deleteDiskCache(key: string) {
if (this.useAccountCache) { if (this.useAccountCache) {
delete this.accountDiskCache.value[key]; delete this.accountDiskCacheSubject.value[key];
this.accountDiskCache.next(this.accountDiskCache.value); this.accountDiskCacheSubject.next(this.accountDiskCacheSubject.value);
} }
} }
} }