From 7f0749ca5c327f3706fdff4914554b2c265a85e1 Mon Sep 17 00:00:00 2001 From: Jacob Fink Date: Fri, 16 Jun 2023 11:46:10 -0400 Subject: [PATCH] share disk cache to fix syncing issues between contexts --- .../platform/services/browser-state.service.ts | 16 +++++++++------- .../src/popup/services/services.module.ts | 9 ++++++++- .../src/platform/abstractions/state.service.ts | 1 + .../src/platform/services/state.service.ts | 13 +++++++------ 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/apps/browser/src/platform/services/browser-state.service.ts b/apps/browser/src/platform/services/browser-state.service.ts index 9bea25ff0e..9d6b770457 100644 --- a/apps/browser/src/platform/services/browser-state.service.ts +++ b/apps/browser/src/platform/services/browser-state.service.ts @@ -1,4 +1,4 @@ -import { BehaviorSubject } from "rxjs"; +import { BehaviorSubject, Observable } from "rxjs"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { StateMigrationService } from "@bitwarden/common/platform/abstractions/state-migration.service"; @@ -33,11 +33,6 @@ export class BrowserStateService protected activeAccountSubject: BehaviorSubject; @sessionSync({ initializer: (b: boolean) => b }) protected activeAccountUnlockedSubject: BehaviorSubject; - @sessionSync({ - initializer: Account.fromJSON as any, // TODO: Remove this any when all any types are removed from Account - initializeAs: "record", - }) - protected accountDiskCache: BehaviorSubject>; protected accountDeserializer = Account.fromJSON; @@ -48,7 +43,8 @@ export class BrowserStateService logService: LogService, stateMigrationService: StateMigrationService, stateFactory: StateFactory, - useAccountCache = false + useAccountCache = true, + accountCache: Observable> = null ) { super( storageService, @@ -59,6 +55,12 @@ export class BrowserStateService stateFactory, 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) { diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index 1b3244064b..e71bdd1c08 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -440,13 +440,20 @@ function getBgService(service: keyof MainBackground) { logService: LogServiceAbstraction, 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("stateService"); + const bgDiskCache = bgStateService().accountDiskCache$; return new BrowserStateService( storageService, secureStorageService, memoryStorageService, logService, stateMigrationService, - new StateFactory(GlobalState, Account) + new StateFactory(GlobalState, Account), + true, + bgDiskCache ); }, deps: [ diff --git a/libs/common/src/platform/abstractions/state.service.ts b/libs/common/src/platform/abstractions/state.service.ts index e36190f12c..6ae3a523cc 100644 --- a/libs/common/src/platform/abstractions/state.service.ts +++ b/libs/common/src/platform/abstractions/state.service.ts @@ -37,6 +37,7 @@ export abstract class StateService { accounts$: Observable<{ [userId: string]: T }>; activeAccount$: Observable; activeAccountUnlocked$: Observable; + accountDiskCache$: Observable>; addAccount: (account: T) => Promise; setActiveUser: (userId: string) => Promise; diff --git a/libs/common/src/platform/services/state.service.ts b/libs/common/src/platform/services/state.service.ts index 7f242bdb7d..97fee6edbd 100644 --- a/libs/common/src/platform/services/state.service.ts +++ b/libs/common/src/platform/services/state.service.ts @@ -95,7 +95,8 @@ export class StateService< private hasBeenInited = false; private isRecoveredSession = false; - protected accountDiskCache = new BehaviorSubject>({}); + protected accountDiskCacheSubject = new BehaviorSubject>({}); + accountDiskCache$ = this.accountDiskCacheSubject.asObservable(); // default account serializer, must be overridden by child class protected accountDeserializer = Account.fromJSON as (json: Jsonify) => TAccount; @@ -2770,7 +2771,7 @@ export class StateService< } if (this.useAccountCache) { - const cachedAccount = this.accountDiskCache.value[options.userId]; + const cachedAccount = this.accountDiskCacheSubject.value[options.userId]; if (cachedAccount != null) { return cachedAccount; } @@ -3166,15 +3167,15 @@ export class StateService< private setDiskCache(key: string, value: TAccount, options?: StorageOptions) { if (this.useAccountCache) { - this.accountDiskCache.value[key] = value; - this.accountDiskCache.next(this.accountDiskCache.value); + this.accountDiskCacheSubject.value[key] = value; + this.accountDiskCacheSubject.next(this.accountDiskCacheSubject.value); } } private deleteDiskCache(key: string) { if (this.useAccountCache) { - delete this.accountDiskCache.value[key]; - this.accountDiskCache.next(this.accountDiskCache.value); + delete this.accountDiskCacheSubject.value[key]; + this.accountDiskCacheSubject.next(this.accountDiskCacheSubject.value); } } }