1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-19 01:33:33 +00:00

[BEEEP] [PM-565] Implement clipboard logic in rust (#4516)

Implement the Desktop clipboard logic natively using rust. This uses the arboard crate for clipboard functionality.

This change consists of 3 portions:
* Rust component.
* Updating renderer to call main using electron ipc.
* Update main to listen to renderer ipc and forward calls to the native clipboard module.
This commit is contained in:
Oscar Hinton
2023-10-02 18:50:57 +02:00
committed by GitHub
parent 6aed74d241
commit 30feb60645
14 changed files with 485 additions and 240 deletions

View File

@@ -15,6 +15,7 @@ import { UpdaterMain } from "./main/updater.main";
import { WindowMain } from "./main/window.main";
import { Account } from "./models/account";
import { BiometricsService, BiometricsServiceAbstraction } from "./platform/main/biometric/index";
import { ClipboardMain } from "./platform/main/clipboard.main";
import { DesktopCredentialStorageListener } from "./platform/main/desktop-credential-storage-listener";
import { ElectronLogService } from "./platform/services/electron-log.service";
import { ElectronStateService } from "./platform/services/electron-state.service";
@@ -39,6 +40,7 @@ export class Main {
trayMain: TrayMain;
biometricsService: BiometricsServiceAbstraction;
nativeMessagingMain: NativeMessagingMain;
clipboardMain: ClipboardMain;
constructor() {
// Set paths for portable builds
@@ -138,6 +140,9 @@ export class Main {
app.getPath("userData"),
app.getPath("exe")
);
this.clipboardMain = new ClipboardMain();
this.clipboardMain.init();
}
bootstrap() {

View File

@@ -0,0 +1,17 @@
import { ipcMain } from "electron";
import { clipboards } from "@bitwarden/desktop-native";
import { ClipboardWriteMessage } from "../types/clipboard";
export class ClipboardMain {
init() {
ipcMain.handle("clipboard.read", async (_event: any, _message: any) => {
return await clipboards.read();
});
ipcMain.handle("clipboard.write", async (_event: any, message: ClipboardWriteMessage) => {
return await clipboards.write(message.text, message.password ?? false);
});
}
}

View File

@@ -1,12 +1,16 @@
import { clipboard, ipcRenderer, shell } from "electron";
import { ipcRenderer, shell } from "electron";
import { ClientType, DeviceType } from "@bitwarden/common/enums";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import {
ClipboardOptions,
PlatformUtilsService,
} from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { BiometricMessage, BiometricStorageAction } from "../../types/biometric-message";
import { isDev, isMacAppStore } from "../../utils";
import { ClipboardWriteMessage } from "../types/clipboard";
export class ElectronPlatformUtilsService implements PlatformUtilsService {
private deviceCache: DeviceType = null;
@@ -117,24 +121,26 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService {
return false;
}
copyToClipboard(text: string, options?: any): void {
const type = options ? options.type : null;
const clearing = options ? !!options.clearing : false;
const clearMs: number = options && options.clearMs ? options.clearMs : null;
clipboard.writeText(text, type);
copyToClipboard(text: string, options?: ClipboardOptions): void {
const clearing = options?.clearing === true;
const clearMs = options?.clearMs ?? null;
ipcRenderer.invoke("clipboard.write", {
text: text,
password: (options?.allowHistory ?? false) === false, // default to false
} satisfies ClipboardWriteMessage);
if (!clearing) {
this.messagingService.send("copiedToClipboard", {
clipboardValue: text,
clearMs: clearMs,
type: type,
clearing: clearing,
});
}
}
readFromClipboard(options?: any): Promise<string> {
const type = options ? options.type : null;
return Promise.resolve(clipboard.readText(type));
readFromClipboard(): Promise<string> {
return ipcRenderer.invoke("clipboard.read");
}
async supportsBiometric(): Promise<boolean> {

View File

@@ -0,0 +1,4 @@
export type ClipboardWriteMessage = {
text: string;
password?: boolean;
};