mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 00:03:56 +00:00
Ps/pm 2910/add browser storage services (#6849)
* Allow for update logic in state update callbacks * Prefer reading updates to sending in stream * Inform state providers when they must deserialize * Update DefaultGlobalState to act more like DefaultUserState * Fully Implement AbstractStorageService * Add KeyDefinitionOptions * Address PR feedback * Prefer testing interactions for ports * Synced memory storage for browser * Fix port handling * Do not stringify port message data * Use messaging storage * Initialize new foreground memory storage services This will need to be rethought for short-lived background pages, but for now the background is the source of truth for memory storage * Use global state for account service * Use BrowserApi listener to avoid safari memory leaks * Fix build errors: debugging and missed impls * Prefer bound arrow functions * JSON Stringify Messages * Prefer `useClass` * Use noop services * extract storage observable to new interface This also reverts changes for the existing services to use foreground/background services. Those are now used only in state providers * Fix web DI * Prefer initializing observable in constructor * Do not use jsonify as equality operator * Remove port listener to avoid memory leaks * Fix logic and type issues --------- Co-authored-by: Justin Baur <19896123+justindbaur@users.noreply.github.com>
This commit is contained in:
@@ -7,6 +7,8 @@ import {
|
||||
LOCALES_DIRECTORY,
|
||||
SYSTEM_LANGUAGE,
|
||||
MEMORY_STORAGE,
|
||||
OBSERVABLE_MEMORY_STORAGE,
|
||||
OBSERVABLE_DISK_STORAGE,
|
||||
} from "@bitwarden/angular/services/injection-tokens";
|
||||
import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module";
|
||||
import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction";
|
||||
@@ -102,6 +104,8 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
|
||||
{ provide: AbstractStorageService, useClass: ElectronRendererStorageService },
|
||||
{ provide: SECURE_STORAGE, useClass: ElectronRendererSecureStorageService },
|
||||
{ provide: MEMORY_STORAGE, useClass: MemoryStorageService },
|
||||
{ provide: OBSERVABLE_MEMORY_STORAGE, useExisting: MEMORY_STORAGE },
|
||||
{ provide: OBSERVABLE_DISK_STORAGE, useExisting: AbstractStorageService },
|
||||
{
|
||||
provide: SystemServiceAbstraction,
|
||||
useClass: SystemService,
|
||||
|
||||
@@ -6,6 +6,9 @@ import { AccountServiceImplementation } from "@bitwarden/common/auth/services/ac
|
||||
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
|
||||
import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state";
|
||||
import { MemoryStorageService } from "@bitwarden/common/platform/services/memory-storage.service";
|
||||
import { NoopMessagingService } from "@bitwarden/common/platform/services/noop-messaging.service";
|
||||
// eslint-disable-next-line import/no-restricted-paths -- We need the implementation to inject, but generally this should not be accessed
|
||||
import { DefaultGlobalStateProvider } from "@bitwarden/common/platform/state/implementations/default-global-state.provider";
|
||||
|
||||
import { MenuMain } from "./main/menu/menu.main";
|
||||
import { MessagingMain } from "./main/messaging.main";
|
||||
@@ -85,6 +88,10 @@ export class Main {
|
||||
storageDefaults["global.vaultTimeoutAction"] = "lock";
|
||||
this.storageService = new ElectronStorageService(app.getPath("userData"), storageDefaults);
|
||||
this.memoryStorageService = new MemoryStorageService();
|
||||
const globalStateProvider = new DefaultGlobalStateProvider(
|
||||
this.memoryStorageService,
|
||||
this.storageService
|
||||
);
|
||||
|
||||
// TODO: this state service will have access to on disk storage, but not in memory storage.
|
||||
// If we could get this to work using the stateService singleton that the rest of the app uses we could save
|
||||
@@ -95,7 +102,11 @@ export class Main {
|
||||
this.memoryStorageService,
|
||||
this.logService,
|
||||
new StateFactory(GlobalState, Account),
|
||||
new AccountServiceImplementation(null, this.logService), // will not broadcast logouts. This is a hack until we can remove messaging dependency
|
||||
new AccountServiceImplementation(
|
||||
new NoopMessagingService(),
|
||||
this.logService,
|
||||
globalStateProvider
|
||||
), // will not broadcast logouts. This is a hack until we can remove messaging dependency
|
||||
false // Do not use disk caching because this will get out of sync with the renderer service
|
||||
);
|
||||
|
||||
|
||||
@@ -11,8 +11,10 @@ export class ElectronRendererStorageService implements AbstractStorageService {
|
||||
get valuesRequireDeserialization(): boolean {
|
||||
return true;
|
||||
}
|
||||
get updates$() {
|
||||
return this.updatesSubject.asObservable();
|
||||
updates$;
|
||||
|
||||
constructor() {
|
||||
this.updates$ = this.updatesSubject.asObservable();
|
||||
}
|
||||
|
||||
get<T>(key: string): Promise<T> {
|
||||
|
||||
@@ -40,6 +40,7 @@ type Options = BaseOptions<"get"> | BaseOptions<"has"> | SaveOptions | BaseOptio
|
||||
export class ElectronStorageService implements AbstractStorageService {
|
||||
private store: ElectronStore;
|
||||
private updatesSubject = new Subject<StorageUpdate>();
|
||||
updates$;
|
||||
|
||||
constructor(dir: string, defaults = {}) {
|
||||
if (!fs.existsSync(dir)) {
|
||||
@@ -50,6 +51,7 @@ export class ElectronStorageService implements AbstractStorageService {
|
||||
name: "data",
|
||||
};
|
||||
this.store = new Store(storeConfig);
|
||||
this.updates$ = this.updatesSubject.asObservable();
|
||||
|
||||
ipcMain.handle("storageService", (event, options: Options) => {
|
||||
switch (options.action) {
|
||||
@@ -68,9 +70,6 @@ export class ElectronStorageService implements AbstractStorageService {
|
||||
get valuesRequireDeserialization(): boolean {
|
||||
return true;
|
||||
}
|
||||
get updates$() {
|
||||
return this.updatesSubject.asObservable();
|
||||
}
|
||||
|
||||
get<T>(key: string): Promise<T> {
|
||||
const val = this.store.get(key) as T;
|
||||
|
||||
Reference in New Issue
Block a user