diff --git a/apps/browser/src/platform/ipc/background-communication-backend.ts b/apps/browser/src/platform/ipc/background-communication-backend.ts deleted file mode 100644 index 1ebb835fa3b..00000000000 --- a/apps/browser/src/platform/ipc/background-communication-backend.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { IpcMessage, isIpcMessage } from "@bitwarden/common/platform/ipc"; -import { MessageQueue } from "@bitwarden/common/platform/ipc/message-queue"; -import { CommunicationBackend, IncomingMessage, OutgoingMessage } from "@bitwarden/sdk-internal"; - -import { BrowserApi } from "../browser/browser-api"; - -export class BackgroundCommunicationBackend implements CommunicationBackend { - private queue = new MessageQueue(); - - constructor() { - BrowserApi.messageListener("platform.ipc", (message, sender) => { - if (!isIpcMessage(message)) { - return; - } - - if (sender.tab?.id === undefined || sender.tab.id === chrome.tabs.TAB_ID_NONE) { - // Ignore messages from non-tab sources - return; - } - - void this.queue.enqueue( - new IncomingMessage(message.message.payload, message.message.destination, { - Web: { id: sender.tab.id }, - }), - ); - }); - } - - async send(message: OutgoingMessage): Promise { - if (typeof message.destination === "object" && "Web" in message.destination) { - await BrowserApi.tabSendMessage( - { id: message.destination.Web.id } as chrome.tabs.Tab, - { type: "bitwarden-ipc-message", message } satisfies IpcMessage, - { frameId: 0 }, - ); - return; - } - - throw new Error("Destination not supported."); - } - - async receive(): Promise { - return this.queue.dequeue(); - } -} diff --git a/apps/browser/src/platform/ipc/ipc-background.service.ts b/apps/browser/src/platform/ipc/ipc-background.service.ts index a87f6bb4acb..155966898f9 100644 --- a/apps/browser/src/platform/ipc/ipc-background.service.ts +++ b/apps/browser/src/platform/ipc/ipc-background.service.ts @@ -1,12 +1,17 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; -import { IpcService } from "@bitwarden/common/platform/ipc"; -import { IpcClient } from "@bitwarden/sdk-internal"; +import { IpcMessage, isIpcMessage, IpcService } from "@bitwarden/common/platform/ipc"; +import { + IpcClient, + IpcCommunicationBackend, + IncomingMessage, + OutgoingMessage, +} from "@bitwarden/sdk-internal"; -import { BackgroundCommunicationBackend } from "./background-communication-backend"; +import { BrowserApi } from "../browser/browser-api"; export class IpcBackgroundService extends IpcService { - private communicationProvider?: BackgroundCommunicationBackend; + private communicationBackend?: IpcCommunicationBackend; constructor(private logService: LogService) { super(); @@ -16,9 +21,46 @@ export class IpcBackgroundService extends IpcService { try { // This function uses classes and functions defined in the SDK, so we need to wait for the SDK to load. await SdkLoadService.Ready; - this.communicationProvider = new BackgroundCommunicationBackend(); + this.communicationBackend = new IpcCommunicationBackend({ + async send(message: OutgoingMessage): Promise { + if (typeof message.destination === "object") { + await BrowserApi.tabSendMessage( + { id: message.destination.Web.id } as chrome.tabs.Tab, + { + type: "bitwarden-ipc-message", + message: { + destination: message.destination, + payload: message.payload, + topic: message.topic, + }, + } satisfies IpcMessage, + { frameId: 0 }, + ); + return; + } - await super.initWithClient(new IpcClient(this.communicationProvider)); + throw new Error("Destination not supported."); + }, + }); + + BrowserApi.messageListener("platform.ipc", (message, sender) => { + if (!isIpcMessage(message)) { + return; + } + + if (sender.tab?.id === undefined || sender.tab.id === chrome.tabs.TAB_ID_NONE) { + // Ignore messages from non-tab sources + return; + } + + this.communicationBackend?.deliver_message( + new IncomingMessage(message.message.payload, message.message.destination, { + Web: { id: sender.tab.id }, + }), + ); + }); + + await super.initWithClient(new IpcClient(this.communicationBackend)); } catch (e) { this.logService.error("[IPC] Initialization failed", e); } diff --git a/apps/web/src/app/platform/ipc/web-communication-provider.ts b/apps/web/src/app/platform/ipc/web-communication-provider.ts deleted file mode 100644 index 787a3c7f3a4..00000000000 --- a/apps/web/src/app/platform/ipc/web-communication-provider.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Injectable } from "@angular/core"; - -import { IpcMessage, isIpcMessage } from "@bitwarden/common/platform/ipc"; -import { MessageQueue } from "@bitwarden/common/platform/ipc/message-queue"; -import { CommunicationBackend, IncomingMessage, OutgoingMessage } from "@bitwarden/sdk-internal"; - -@Injectable({ providedIn: "root" }) -export class WebCommunicationProvider implements CommunicationBackend { - private queue = new MessageQueue(); - - constructor() { - window.addEventListener("message", async (event: MessageEvent) => { - if (event.origin !== window.origin) { - return; - } - - const message = event.data; - if (!isIpcMessage(message)) { - return; - } - - void this.queue.enqueue( - new IncomingMessage( - message.message.payload, - message.message.destination, - "BrowserBackground", - ), - ); - }); - } - - async send(message: OutgoingMessage): Promise { - if (message.destination === "BrowserBackground") { - window.postMessage( - { type: "bitwarden-ipc-message", message } satisfies IpcMessage, - window.location.origin, - ); - return; - } - - throw new Error(`Destination not supported: ${message.destination}`); - } - - receive(): Promise { - return this.queue.dequeue(); - } -} 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 59a715f31f5..e088de2473b 100644 --- a/apps/web/src/app/platform/ipc/web-ipc.service.ts +++ b/apps/web/src/app/platform/ipc/web-ipc.service.ts @@ -2,22 +2,65 @@ import { inject } from "@angular/core"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; -import { IpcService } from "@bitwarden/common/platform/ipc"; -import { IpcClient } from "@bitwarden/sdk-internal"; - -import { WebCommunicationProvider } from "./web-communication-provider"; +import { IpcMessage, IpcService, isIpcMessage } from "@bitwarden/common/platform/ipc"; +import { + IncomingMessage, + IpcClient, + IpcCommunicationBackend, + OutgoingMessage, +} from "@bitwarden/sdk-internal"; export class WebIpcService extends IpcService { private logService = inject(LogService); - private communicationProvider?: WebCommunicationProvider; + private communicationBackend?: IpcCommunicationBackend; override async init() { try { // This function uses classes and functions defined in the SDK, so we need to wait for the SDK to load. await SdkLoadService.Ready; - this.communicationProvider = new WebCommunicationProvider(); - await super.initWithClient(new IpcClient(this.communicationProvider)); + this.communicationBackend = new IpcCommunicationBackend({ + async send(message: OutgoingMessage): Promise { + if (message.destination === "BrowserBackground") { + window.postMessage( + { + type: "bitwarden-ipc-message", + message: { + destination: message.destination, + payload: message.payload, + topic: message.topic, + }, + } satisfies IpcMessage, + window.location.origin, + ); + return; + } + + throw new Error(`Destination not supported: ${message.destination}`); + }, + }); + + window.addEventListener("message", async (event: MessageEvent) => { + if (event.origin !== window.origin) { + return; + } + + const message = event.data; + if (!isIpcMessage(message)) { + return; + } + + this.communicationBackend?.deliver_message( + new IncomingMessage( + message.message.payload, + message.message.destination, + "BrowserBackground", + message.message.topic, + ), + ); + }); + + await super.initWithClient(new IpcClient(this.communicationBackend)); } catch (e) { this.logService.error("[IPC] Initialization failed", e); } diff --git a/libs/common/src/platform/ipc/ipc-message.ts b/libs/common/src/platform/ipc/ipc-message.ts index 78cce011f49..c0702f07567 100644 --- a/libs/common/src/platform/ipc/ipc-message.ts +++ b/libs/common/src/platform/ipc/ipc-message.ts @@ -2,7 +2,7 @@ import type { OutgoingMessage } from "@bitwarden/sdk-internal"; export interface IpcMessage { type: "bitwarden-ipc-message"; - message: OutgoingMessage; + message: Omit; } export function isIpcMessage(message: any): message is IpcMessage { diff --git a/libs/common/src/platform/ipc/ipc.service.ts b/libs/common/src/platform/ipc/ipc.service.ts index 7d2c7479be7..c3cd77d9850 100644 --- a/libs/common/src/platform/ipc/ipc.service.ts +++ b/libs/common/src/platform/ipc/ipc.service.ts @@ -25,11 +25,11 @@ export abstract class IpcService { this._client = client; this._messages$ = new Observable((subscriber) => { let isSubscribed = true; - const receiveLoop = async () => { + const subscription = await this.client.subscribe(); while (isSubscribed) { try { - const message = await this.client.receive(); + const message = await subscription.receive(); subscriber.next(message); } catch (error) { subscriber.error(error); diff --git a/package-lock.json b/package-lock.json index 6cc1e32ef4d..d8be3d96184 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "@angular/platform-browser": "18.2.13", "@angular/platform-browser-dynamic": "18.2.13", "@angular/router": "18.2.13", - "@bitwarden/sdk-internal": "0.2.0-main.137", + "@bitwarden/sdk-internal": "0.2.0-main.159", "@electron/fuses": "1.8.0", "@emotion/css": "11.13.5", "@koa/multer": "3.0.2", @@ -4700,9 +4700,9 @@ "link": true }, "node_modules/@bitwarden/sdk-internal": { - "version": "0.2.0-main.137", - "resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.2.0-main.137.tgz", - "integrity": "sha512-Df0pB5tOEc4WiMjskunTrqHulPzenFv8C61sqsBhHfy80xcf5kU5JyPd4asbf3e4uNS6QGXptd8imp09AuiFEA==", + "version": "0.2.0-main.159", + "resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.2.0-main.159.tgz", + "integrity": "sha512-vliX5w/A6fuKWZJpDZTCPV4EU5CFrrs6zAv0aQaUQXF9LqL1YVh113D1NhOMuG2ILLWs2kDcTKiprvWFSTu1dg==", "license": "GPL-3.0" }, "node_modules/@bitwarden/send-ui": { diff --git a/package.json b/package.json index e82a010b9b4..5035e1b1da8 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "@angular/platform-browser": "18.2.13", "@angular/platform-browser-dynamic": "18.2.13", "@angular/router": "18.2.13", - "@bitwarden/sdk-internal": "0.2.0-main.137", + "@bitwarden/sdk-internal": "0.2.0-main.159", "@electron/fuses": "1.8.0", "@emotion/css": "11.13.5", "@koa/multer": "3.0.2",