1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-03 18:23:57 +00:00

feat: scaffold ipc service on desktop

This commit is contained in:
Andreas Coroiu
2025-10-17 13:57:05 +02:00
parent 5281da8fad
commit 29f8a864d1
5 changed files with 201 additions and 0 deletions

View File

@@ -13,6 +13,7 @@ import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platfor
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service";
import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service";
import { IpcService } from "@bitwarden/common/platform/ipc";
import { ServerNotificationsService } from "@bitwarden/common/platform/server-notifications";
import { ContainerService } from "@bitwarden/common/platform/services/container.service";
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
@@ -52,6 +53,7 @@ export class InitService {
private autofillService: DesktopAutofillService,
private autotypeService: DesktopAutotypeService,
private sdkLoadService: SdkLoadService,
private ipcService: IpcService,
@Inject(DOCUMENT) private document: Document,
private readonly migrationRunner: MigrationRunner,
) {}
@@ -94,6 +96,7 @@ export class InitService {
await this.autofillService.init();
await this.autotypeService.init();
await this.ipcService.init();
};
}
}

View File

@@ -83,6 +83,7 @@ import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-
import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service";
import { AbstractStorageService } from "@bitwarden/common/platform/abstractions/storage.service";
import { SystemService as SystemServiceAbstraction } from "@bitwarden/common/platform/abstractions/system.service";
import { IpcService } 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";
@@ -133,6 +134,7 @@ import { ElectronRendererMessageSender } from "../../platform/services/electron-
import { ElectronRendererSecureStorageService } from "../../platform/services/electron-renderer-secure-storage.service";
import { ElectronRendererStorageService } from "../../platform/services/electron-renderer-storage.service";
import { I18nRendererService } from "../../platform/services/i18n.renderer.service";
import { IpcRendererService } from "../../platform/services/ipc-renderer.service";
import { fromIpcMessaging } from "../../platform/utils/from-ipc-messaging";
import { fromIpcSystemTheme } from "../../platform/utils/from-ipc-system-theme";
import { BiometricMessageHandlerService } from "../../services/biometric-message-handler.service";
@@ -476,6 +478,11 @@ const safeProviders: SafeProvider[] = [
useClass: DesktopAutotypeDefaultSettingPolicy,
deps: [AccountServiceAbstraction, AuthServiceAbstraction, InternalPolicyService, ConfigService],
}),
safeProvider({
provide: IpcService,
useClass: IpcRendererService,
deps: [],
}),
];
@NgModule({

View File

@@ -14,6 +14,7 @@ import { ClientType } from "@bitwarden/common/enums";
import { EncryptServiceImplementation } from "@bitwarden/common/key-management/crypto/services/encrypt.service.implementation";
import { RegionConfig } from "@bitwarden/common/platform/abstractions/environment.service";
import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service";
import { IpcService } from "@bitwarden/common/platform/ipc";
import { Message, MessageSender } from "@bitwarden/common/platform/messaging";
// eslint-disable-next-line no-restricted-imports -- For dependency creation
import { SubjectMessageSender } from "@bitwarden/common/platform/messaging/internal";
@@ -56,6 +57,7 @@ import { ElectronLogMainService } from "./platform/services/electron-log.main.se
import { ElectronStorageService } from "./platform/services/electron-storage.service";
import { EphemeralValueStorageService } from "./platform/services/ephemeral-value-storage.main.service";
import { I18nMainService } from "./platform/services/i18n.main.service";
import { IpcMainService } from "./platform/services/ipc.main.service";
import { SSOLocalhostCallbackService } from "./platform/services/sso-localhost-callback.service";
import { ElectronMainMessagingService } from "./services/electron-main-messaging.service";
import { MainSdkLoadService } from "./services/main-sdk-load-service";
@@ -91,6 +93,7 @@ export class Main {
sshAgentService: MainSshAgentService;
sdkLoadService: SdkLoadService;
mainDesktopAutotypeService: MainDesktopAutotypeService;
ipcService: IpcService;
constructor() {
// Set paths for portable builds
@@ -311,6 +314,8 @@ export class Main {
this.windowMain,
);
this.ipcService = new IpcMainService(this.logService, app);
app
.whenReady()
.then(() => {
@@ -405,6 +410,7 @@ export class Main {
});
await this.sdkLoadService.loadAndInit();
await this.ipcService.init();
},
(e: any) => {
this.logService.error("Error while running migrations:", e);

View File

@@ -0,0 +1,90 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { inject, Injectable } 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 {
IncomingMessage,
IpcClient,
IpcCommunicationBackend,
ipcRegisterDiscoverHandler,
OutgoingMessage,
} from "@bitwarden/sdk-internal";
export class IpcRendererService extends IpcService {
private logService = inject(LogService);
private platformUtilsService = inject(PlatformUtilsService);
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.communicationBackend = new IpcCommunicationBackend({
async send(message: OutgoingMessage): Promise<void> {
if (message.destination === "DesktopRenderer") {
throw new Error(
`Destination not supported: ${message.destination} (cannot send messages to self)`,
);
}
throw new Error("Not implemented");
// if (message.destination === "BrowserBackground" || message.destination === "ElectronMain") {
// window.postMessage(
// {
// type: "bitwarden-ipc-message",
// message: {
// destination: message.destination,
// payload: [...message.payload],
// topic: message.topic,
// },
// } satisfies IpcMessage,
// window.location.origin,
// );
// return;
// }
},
});
// window.addEventListener("message", async (event: MessageEvent) => {
// if (event.origin !== window.origin) {
// return;
// }
// const message = event.data;
// if (!isIpcMessage(message)) {
// return;
// }
// if (
// typeof message.message.destination !== "object" ||
// message.message.destination.Web == undefined
// ) {
// return;
// }
// this.communicationBackend?.receive(
// new IncomingMessage(
// new Uint8Array(message.message.payload),
// message.message.destination,
// "BrowserBackground",
// message.message.topic,
// ),
// );
// });
await super.initWithClient(new IpcClient(this.communicationBackend));
if (this.platformUtilsService.isDev()) {
await ipcRegisterDiscoverHandler(this.client, {
version: await this.platformUtilsService.getApplicationVersion(),
});
}
} catch (e) {
this.logService.error("[IPC] Initialization failed", e);
}
}
}

View File

@@ -0,0 +1,95 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
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 {
IncomingMessage,
IpcClient,
IpcCommunicationBackend,
ipcRegisterDiscoverHandler,
OutgoingMessage,
} from "@bitwarden/sdk-internal";
import { isDev } from "../../utils";
export class IpcMainService extends IpcService {
private communicationBackend?: IpcCommunicationBackend;
constructor(
private logService: LogService,
private app: Electron.App,
) {
super();
}
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.communicationBackend = new IpcCommunicationBackend({
async send(message: OutgoingMessage): Promise<void> {
if (message.destination === "DesktopMain") {
throw new Error(
`Destination not supported: ${message.destination} (cannot send messages to self)`,
);
}
throw new Error("Not implemented");
// if (message.destination === "BrowserBackground" || message.destination === "ElectronMain") {
// window.postMessage(
// {
// type: "bitwarden-ipc-message",
// message: {
// destination: message.destination,
// payload: [...message.payload],
// topic: message.topic,
// },
// } satisfies IpcMessage,
// window.location.origin,
// );
// return;
// }
},
});
// window.addEventListener("message", async (event: MessageEvent) => {
// if (event.origin !== window.origin) {
// return;
// }
// const message = event.data;
// if (!isIpcMessage(message)) {
// return;
// }
// if (
// typeof message.message.destination !== "object" ||
// message.message.destination.Web == undefined
// ) {
// return;
// }
// this.communicationBackend?.receive(
// new IncomingMessage(
// new Uint8Array(message.message.payload),
// message.message.destination,
// "BrowserBackground",
// message.message.topic,
// ),
// );
// });
await super.initWithClient(new IpcClient(this.communicationBackend));
if (isDev()) {
await ipcRegisterDiscoverHandler(this.client, {
version: await this.app.getVersion(),
});
}
} catch (e) {
this.logService.error("[IPC] Initialization failed", e);
}
}
}