diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 97bfe804411..cff783942fe 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -131,7 +131,7 @@ import { } from "@bitwarden/common/platform/abstractions/storage.service"; import { SystemService as SystemServiceAbstraction } from "@bitwarden/common/platform/abstractions/system.service"; import { ActionsService } from "@bitwarden/common/platform/actions/actions-service"; -import { IpcService } from "@bitwarden/common/platform/ipc"; +import { IpcService, IpcSessionRepository } from "@bitwarden/common/platform/ipc"; import { Message, MessageListener, MessageSender } from "@bitwarden/common/platform/messaging"; // eslint-disable-next-line no-restricted-imports -- Used for dependency creation import { SubjectMessageSender } from "@bitwarden/common/platform/messaging/internal"; @@ -1476,7 +1476,12 @@ export default class MainBackground { ); this.ipcContentScriptManagerService = new IpcContentScriptManagerService(this.configService); - this.ipcService = new IpcBackgroundService(this.platformUtilsService, this.logService); + const ipcSessionRepository = new IpcSessionRepository(this.stateProvider); + this.ipcService = new IpcBackgroundService( + this.platformUtilsService, + this.logService, + ipcSessionRepository, + ); this.endUserNotificationService = new DefaultEndUserNotificationService( this.stateProvider, diff --git a/apps/browser/src/platform/ipc/ipc-background.service.ts b/apps/browser/src/platform/ipc/ipc-background.service.ts index 911ca931c70..9fc2ca24b6a 100644 --- a/apps/browser/src/platform/ipc/ipc-background.service.ts +++ b/apps/browser/src/platform/ipc/ipc-background.service.ts @@ -8,6 +8,7 @@ import { OutgoingMessage, ipcRegisterDiscoverHandler, IpcClient, + IpcSessionRepository, } from "@bitwarden/sdk-internal"; import { BrowserApi } from "../browser/browser-api"; @@ -18,6 +19,7 @@ export class IpcBackgroundService extends IpcService { constructor( private platformUtilsService: PlatformUtilsService, private logService: LogService, + private sessionRepository: IpcSessionRepository, ) { super(); } @@ -70,7 +72,9 @@ export class IpcBackgroundService extends IpcService { ); }); - await super.initWithClient(new IpcClient(this.communicationBackend)); + await super.initWithClient( + IpcClient.newWithClientManagedSessions(this.communicationBackend, this.sessionRepository), + ); if (this.platformUtilsService.isDev()) { await ipcRegisterDiscoverHandler(this.client, { diff --git a/apps/web/src/app/platform/ipc/web-ipc.service.ts b/apps/web/src/app/platform/ipc/web-ipc.service.ts index 590c1f36cc4..c6614759b44 100644 --- a/apps/web/src/app/platform/ipc/web-ipc.service.ts +++ b/apps/web/src/app/platform/ipc/web-ipc.service.ts @@ -3,7 +3,12 @@ import { inject } from "@angular/core"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; -import { IpcMessage, IpcService, isIpcMessage } from "@bitwarden/common/platform/ipc"; +import { + IpcMessage, + IpcService, + isIpcMessage, + IpcSessionRepository, +} from "@bitwarden/common/platform/ipc"; import { IncomingMessage, IpcClient, @@ -15,6 +20,7 @@ import { export class WebIpcService extends IpcService { private logService = inject(LogService); private platformUtilsService = inject(PlatformUtilsService); + private sessionRepository = inject(IpcSessionRepository); private communicationBackend?: IpcCommunicationBackend; override async init() { @@ -70,7 +76,9 @@ export class WebIpcService extends IpcService { ); }); - await super.initWithClient(new IpcClient(this.communicationBackend)); + await super.initWithClient( + IpcClient.newWithClientManagedSessions(this.communicationBackend, this.sessionRepository), + ); if (this.platformUtilsService.isDev()) { await ipcRegisterDiscoverHandler(this.client, { diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index a608b290f09..3c9062d5787 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -226,6 +226,7 @@ import { SystemService } from "@bitwarden/common/platform/abstractions/system.se import { ValidationService as ValidationServiceAbstraction } from "@bitwarden/common/platform/abstractions/validation.service"; import { ActionsService } from "@bitwarden/common/platform/actions"; import { UnsupportedActionsService } from "@bitwarden/common/platform/actions/unsupported-actions.service"; +import { IpcSessionRepository } from "@bitwarden/common/platform/ipc"; import { Message, MessageListener, MessageSender } from "@bitwarden/common/platform/messaging"; // eslint-disable-next-line no-restricted-imports -- Used for dependency injection import { SubjectMessageSender } from "@bitwarden/common/platform/messaging/internal"; @@ -1743,6 +1744,7 @@ const safeProviders: SafeProvider[] = [ useClass: DefaultNewDeviceVerificationComponentService, deps: [], }), + safeProvider(IpcSessionRepository), safeProvider({ provide: PremiumInterestStateService, useClass: NoopPremiumInterestStateService, diff --git a/libs/common/src/platform/ipc/index.ts b/libs/common/src/platform/ipc/index.ts index f1acccdddbf..3fa6aeb627d 100644 --- a/libs/common/src/platform/ipc/index.ts +++ b/libs/common/src/platform/ipc/index.ts @@ -1,2 +1,3 @@ export * from "./ipc-message"; export * from "./ipc.service"; +export * from "./ipc-session-repository"; diff --git a/libs/common/src/platform/ipc/ipc-session-repository.ts b/libs/common/src/platform/ipc/ipc-session-repository.ts new file mode 100644 index 00000000000..8c0752ed2fb --- /dev/null +++ b/libs/common/src/platform/ipc/ipc-session-repository.ts @@ -0,0 +1,44 @@ +import { firstValueFrom, map } from "rxjs"; + +import { Endpoint, IpcSessionRepository as SdkIpcSessionRepository } from "@bitwarden/sdk-internal"; + +import { GlobalState, IPC_MEMORY, KeyDefinition, StateProvider } from "../state"; + +const IPC_SESSIONS = KeyDefinition.record(IPC_MEMORY, "ipcSessions", { + deserializer: (value: object) => value, +}); + +export class IpcSessionRepository implements SdkIpcSessionRepository { + private states: GlobalState>; + + constructor(private stateProvider: StateProvider) { + this.states = this.stateProvider.getGlobal(IPC_SESSIONS); + } + + get(endpoint: Endpoint): Promise { + return firstValueFrom(this.states.state$.pipe(map((s) => s?.[endpointToString(endpoint)]))); + } + + async save(endpoint: Endpoint, session: any): Promise { + await this.states.update((s) => ({ + ...s, + [endpointToString(endpoint)]: session, + })); + } + + async remove(endpoint: Endpoint): Promise { + await this.states.update((s) => { + const newState = { ...s }; + delete newState[endpointToString(endpoint)]; + return newState; + }); + } +} + +function endpointToString(endpoint: Endpoint): string { + if (typeof endpoint === "object" && "Web" in endpoint) { + return `Web(${endpoint.Web.id})`; + } + + return endpoint; +} diff --git a/libs/state/src/core/state-definitions.ts b/libs/state/src/core/state-definitions.ts index 7b1d75b2985..9b3bf64f405 100644 --- a/libs/state/src/core/state-definitions.ts +++ b/libs/state/src/core/state-definitions.ts @@ -127,6 +127,7 @@ export const CRYPTO_MEMORY = new StateDefinition("crypto", "memory"); export const DESKTOP_SETTINGS_DISK = new StateDefinition("desktopSettings", "disk"); export const ENVIRONMENT_DISK = new StateDefinition("environment", "disk"); export const ENVIRONMENT_MEMORY = new StateDefinition("environment", "memory"); +export const IPC_MEMORY = new StateDefinition("ipc", "memory"); export const POPUP_VIEW_MEMORY = new StateDefinition("popupView", "memory", { browser: "memory-large-object", });