网站搜索

typescript - 在 electron 渲染器中使用隔离世界 API


我已经使用...创建了我的 Electron 应用

create-electron-app $projDir --template=vite-typescript

在我的 BrowserWindow 的 webpreferences 中,我已经设置了

contextIsolation: true
nodeIntegration: false

我已经在 preload.ts 中定义了我想在 Renderer 上下文中使用的 API,如下所示:

const WORLD_ID: number = 1004;
const API_KEY: string = "api";

interface IApi {
    myFun: <T>(...args: any) => Promise<T>;
}

const api: IApi = {
    myFun: <T>(...args: any) => ipcRenderer.invoke("my-event", ...args) as Promise<T>
}

contextBridge.exposeInIsolatedWorld(
    WORLD_ID, API_KEY, api 
);

export { type IApi, API_KEY, WORLD_ID };

我已经为该 API 定义了一个 interface.d.ts:

import { type IApi, API_KEY } from '@/preload';

declare global {
    interface Window {
        [API_KEY]: IApi 
    }
}

文档 (https://www.electronjs.org/docs/latest/api/context-bridge) 表示我现在可以像这样使用该 API:

// Renderer (In isolated world id1004)

window.api.myFun()
  1. 我找不到任何关于如何在隔离世界中运行渲染器的例子(正如文档中友好提到的那样)。你能帮忙吗?
  2. webFrame.executeInIsolatedWorld() 无法工作,因为 webFrame 需要 path 模块,而该模块在渲染进程中不可用。有替代方法吗?

答案#1

据我所知,隔离世界可以用于提高安全性,适用于您希望在 Electron 应用的渲染进程中运行未知或不受信任的脚本的场景。想象一下某种插件/扩展系统,您的应用程序的终端用户可以安装并运行其他用户编写的脚本。您不希望这些扩展脚本相互干扰,或者干扰您自己信任的渲染脚本。

默认情况下,在隔离世界中执行的脚本可以访问 DOM API 和 JavaScript 内置对象。你可以使用 Electron 的 contextBridge.exposeInIsolatedWorld 让隔离脚本访问额外的 API。

例如,以下预加载脚本暴露了两个 API:

  • extensionAPI 在主世界中可用。它提供了一个函数 extension.execute,允许应用的网页前端在隔离世界 1000 中执行脚本。
  • processAPI 可在隔离世界 1000 中使用。它允许扩展脚本访问 Node.js process API 的一个子集,特别是引擎和库版本。
// preload.ts
import { contextBridge, webFrame } from "electron";

const extensionAPI = {
  execute: async (source: string): Promise<void> => {
    await webFrame.executeJavaScriptInIsolatedWorld(1000, [{ code: source }]);
  },
};
contextBridge.exposeInMainWorld("extension", extensionAPI);

const processAPI = {
  versions: process.versions
};
contextBridge.exposeInIsolatedWorld(1000, "process", process);

现在,你的前端代码在主世界中运行,可以调用 extension.execute 来在隔离世界中执行某些脚本。例如:

extension.execute("console.log('Hello, Electron', process.versions.electron)");

这个例子有点牵强,并且可能违反了一些安全最佳实践,因为它在同一个隔离世界中运行所有扩展脚本。我希望它能说明隔离世界 API 的使用方法。