From 45a1ff7f04d13dd6f0d125a7fac9eddc947be150 Mon Sep 17 00:00:00 2001 From: Andreas Coroiu Date: Tue, 17 Dec 2024 14:33:34 +0100 Subject: [PATCH] feat: somewhat complete web <-> browser link --- .../browser/src/background/main.background.ts | 2 +- .../platform/ipc/ipc-background.service.ts | 34 +++++++++++++++++-- apps/web/src/app/core/core.module.ts | 8 +++++ apps/web/src/app/core/init.service.ts | 3 ++ .../src/app/platform/ipc/web-ipc.service.ts | 31 ++++++++++++----- libs/common/src/platform/ipc/ipc.service.ts | 12 +++++-- 6 files changed, 74 insertions(+), 16 deletions(-) diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index f9380410de..8a2030799d 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -1251,7 +1251,7 @@ export default class MainBackground { this.inlineMenuFieldQualificationService = new InlineMenuFieldQualificationService(); - this.ipcService = new IpcBackgroundService(); + this.ipcService = new IpcBackgroundService(this.sdkService); } async bootstrap() { diff --git a/apps/browser/src/platform/ipc/ipc-background.service.ts b/apps/browser/src/platform/ipc/ipc-background.service.ts index 6c7183bdda..6c4510fc0e 100644 --- a/apps/browser/src/platform/ipc/ipc-background.service.ts +++ b/apps/browser/src/platform/ipc/ipc-background.service.ts @@ -1,17 +1,45 @@ -import { IpcService, isIpcMessage } from "@bitwarden/common/platform/ipc"; +import { Observable } from "rxjs"; + +import { IpcLink, IpcMessage, IpcService, isIpcMessage } from "@bitwarden/common/platform/ipc"; import { BrowserApi } from "../browser/browser-api"; export class IpcBackgroundService extends IpcService { + private links = new Map(); + override async init() { await super.init(); - BrowserApi.messageListener("platform.ipc", (message) => { + BrowserApi.messageListener("platform.ipc", (message, sender) => { if (!isIpcMessage(message)) { return; } - console.log("Received IPC message", message); + if (!this.links.has(sender.documentId)) { + this.links.set( + sender.documentId, + new IpcLink( + async (data) => + BrowserApi.sendMessage("platform.ipc", { + type: "bitwarden-ipc-message", + payload: data, + } satisfies IpcMessage), + new Observable((subscriber) => { + const handler = (message: unknown) => { + if (!isIpcMessage(message)) { + return; + } + subscriber.next(message.payload); + }; + + BrowserApi.addListener(chrome.runtime.onMessage, handler); + + return () => BrowserApi.removeListener(chrome.runtime.onMessage, handler); + }), + [{ Web: sender.documentId }], + ), + ); + } }); } } diff --git a/apps/web/src/app/core/core.module.ts b/apps/web/src/app/core/core.module.ts index 2dd1db9fdb..f594bf8815 100644 --- a/apps/web/src/app/core/core.module.ts +++ b/apps/web/src/app/core/core.module.ts @@ -67,8 +67,10 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service" import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { SdkClientFactory } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory"; +import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service"; import { AbstractStorageService } from "@bitwarden/common/platform/abstractions/storage.service"; import { ThemeType } from "@bitwarden/common/platform/enums"; +import { IpcService } from "@bitwarden/common/platform/ipc"; import { AppIdService as DefaultAppIdService } from "@bitwarden/common/platform/services/app-id.service"; import { MemoryStorageService } from "@bitwarden/common/platform/services/memory-storage.service"; // eslint-disable-next-line import/no-restricted-paths -- Implementation for memory storage @@ -108,6 +110,7 @@ import { HtmlStorageService } from "../core/html-storage.service"; import { I18nService } from "../core/i18n.service"; import { WebProcessReloadService } from "../key-management/services/web-process-reload.service"; import { WebBiometricsService } from "../key-management/web-biometric.service"; +import { WebIpcService } from "../platform/ipc/web-ipc.service"; import { WebEnvironmentService } from "../platform/web-environment.service"; import { WebMigrationRunner } from "../platform/web-migration-runner"; import { WebSdkClientFactory } from "../platform/web-sdk-client-factory"; @@ -313,6 +316,11 @@ const safeProviders: SafeProvider[] = [ useClass: WebLoginDecryptionOptionsService, deps: [MessagingService, RouterService, AcceptOrganizationInviteService], }), + safeProvider({ + provide: IpcService, + useClass: WebIpcService, + deps: [SdkService], + }), ]; @NgModule({ diff --git a/apps/web/src/app/core/init.service.ts b/apps/web/src/app/core/init.service.ts index b3e6d691f7..ef8d778959 100644 --- a/apps/web/src/app/core/init.service.ts +++ b/apps/web/src/app/core/init.service.ts @@ -15,6 +15,7 @@ import { ContainerService } from "@bitwarden/common/platform/services/container. import { UserAutoUnlockKeyService } from "@bitwarden/common/platform/services/user-auto-unlock-key.service"; import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service"; import { VaultTimeoutService } from "@bitwarden/common/services/vault-timeout/vault-timeout.service"; +import { IpcService } from "@bitwarden/common/src/platform/ipc"; import { KeyService as KeyServiceAbstraction } from "@bitwarden/key-management"; import { VersionService } from "../platform/version.service"; @@ -35,6 +36,7 @@ export class InitService { private userAutoUnlockKeyService: UserAutoUnlockKeyService, private accountService: AccountService, private versionService: VersionService, + private ipcService: IpcService, @Inject(DOCUMENT) private document: Document, ) {} @@ -58,6 +60,7 @@ export class InitService { htmlEl.classList.add("locale_" + this.i18nService.translationLocale); this.themingService.applyThemeChangesTo(this.document); this.versionService.applyVersionToWindow(); + void this.ipcService.init(); const containerService = new ContainerService(this.keyService, this.encryptService); containerService.attachToGlobal(this.win); 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 daf2630904..9204697983 100644 --- a/apps/web/src/app/platform/ipc/web-ipc.service.ts +++ b/apps/web/src/app/platform/ipc/web-ipc.service.ts @@ -1,16 +1,29 @@ -import { IpcService, isIpcMessage } from "@bitwarden/common/platform/ipc"; +import { Observable } from "rxjs"; + +import { IpcLink, IpcService, isIpcMessage } from "@bitwarden/common/platform/ipc"; export class WebIpcService extends IpcService { + private static LinkToExtensionBackground = new IpcLink( + async (data) => window.postMessage(data, window.location.origin), + new Observable((subscriber) => { + const listener = (event: MessageEvent) => { + const message = event.data; + if (!isIpcMessage(message)) { + return; + } + + subscriber.next(message.payload); + }; + window.addEventListener("message", listener); + + return () => window.removeEventListener("message", listener); + }), + ["BrowserBackground"], + ); + override async init() { await super.init(); - window.addEventListener("message", (event) => { - const message = event.data; - if (!isIpcMessage(message)) { - return; - } - - console.log("WEB Received IPC message", message); - }); + this.manager.register_link(WebIpcService.LinkToExtensionBackground); } } diff --git a/libs/common/src/platform/ipc/ipc.service.ts b/libs/common/src/platform/ipc/ipc.service.ts index 75b8b5ada6..121c6f954a 100644 --- a/libs/common/src/platform/ipc/ipc.service.ts +++ b/libs/common/src/platform/ipc/ipc.service.ts @@ -1,11 +1,17 @@ -// import { Manager } from "@bitwarden/sdk-internal"; +import { firstValueFrom, map } from "rxjs"; + +import { Manager } from "@bitwarden/sdk-internal"; import { SdkService } from "../abstractions/sdk/sdk.service"; export abstract class IpcService { - // protected manager = new Manager(); + protected manager: Manager; constructor(private sdkService: SdkService) {} - async init() {} + async init() { + await firstValueFrom( + this.sdkService.client$.pipe(map((client) => client.ipc().create_manager())), + ); + } }