contextBridge
History
Version(s) | Changes |
---|---|
None |
|
在隔离的上下文之间创建安全、双向、同步的桥梁
¥Create a safe, bi-directional, synchronous bridge across isolated contexts
进程:渲染器
¥Process: Renderer
下面给出了从独立的预加载脚本向渲染器公开 API 的示例:
¥An example of exposing an API to a renderer from an isolated preload script is given below:
// Preload (Isolated World)
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
// Renderer (Main World)
window.electron.doThing()
词汇表
¥Glossary
主世界
¥Main World
"主世界" 是主渲染器代码运行的 JavaScript 上下文。默认情况下,你在渲染器中加载的页面会执行此世界中的代码。
¥The "Main World" is the JavaScript context that your main renderer code runs in. By default, the page you load in your renderer executes code in this world.
孤立的世界
¥Isolated World
当 webPreferences
中启用 contextIsolation
时(这是自 Electron 12.0.0 以来的默认行为),你的 preload
脚本将在 "孤立的世界" 中运行。你可以在 security 文档中阅读有关上下文隔离及其影响的更多信息。
¥When contextIsolation
is enabled in your webPreferences
(this is the default behavior since Electron 12.0.0), your preload
scripts run in an
"Isolated World". You can read more about context isolation and what it affects in the
security docs.
方法
¥Methods
contextBridge
模块有以下方法:
¥The contextBridge
module has the following methods:
contextBridge.exposeInMainWorld(apiKey, api)
-
apiKey
字符串 - 将 API 注入window
的关键。该 API 将在window[apiKey]
上访问。¥
apiKey
string - The key to inject the API ontowindow
with. The API will be accessible onwindow[apiKey]
. -
api
任意 - 你的 API,有关此 API 是什么及其工作原理的更多信息如下。¥
api
any - Your API, more information on what this API can be and how it works is available below.
contextBridge.exposeInIsolatedWorld(worldId, apiKey, api)
-
worldId
整数 - 要注入 API 的世界的 ID。0
是默认世界,999
是 Electron 的contextIsolation
功能使用的世界。使用 999 会公开预加载上下文的对象。我们建议在创建隔离世界时使用 1000+。¥
worldId
Integer - The ID of the world to inject the API into.0
is the default world,999
is the world used by Electron'scontextIsolation
feature. Using 999 would expose the object for preload context. We recommend using 1000+ while creating isolated world. -
apiKey
字符串 - 将 API 注入window
的关键。该 API 将在window[apiKey]
上访问。¥
apiKey
string - The key to inject the API ontowindow
with. The API will be accessible onwindow[apiKey]
. -
api
任意 - 你的 API,有关此 API 是什么及其工作原理的更多信息如下。¥
api
any - Your API, more information on what this API can be and how it works is available below.
用法
¥Usage
API
提供给 exposeInMainWorld
的 api
必须是 Function
、string
、number
、Array
、boolean
,或键为字符串、值为 Function
、string
、number
、Array
、boolean
的对象,或满足相同条件的其他嵌套对象。
¥The api
provided to exposeInMainWorld
must be a Function
, string
, number
, Array
, boolean
, or an object
whose keys are strings and values are a Function
, string
, number
, Array
, boolean
, or another nested object that meets the same conditions.
Function
值被代理到其他上下文,并且所有其他值都被复制和冻结。API 中发送的任何数据/基础类型都变得不可变,并且桥两侧的更新不会导致另一侧的更新。
¥Function
values are proxied to the other context and all other values are copied and frozen. Any data / primitives sent in
the API become immutable and updates on either side of the bridge do not result in an update on the other side.
复杂 API 的示例如下所示:
¥An example of a complex API is shown below:
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing'),
myPromises: [Promise.resolve(), Promise.reject(new Error('whoops'))],
anAsyncFunction: async () => 123,
data: {
myFlags: ['a', 'b', 'c'],
bootTime: 1234
},
nestedAPI: {
evenDeeper: {
youCanDoThisAsMuchAsYouWant: {
fn: () => ({
returnData: 123
})
}
}
}
}
)
exposeInIsolatedWorld
的示例如下所示:
¥An example of exposeInIsolatedWorld
is shown below:
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInIsolatedWorld(
1004,
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
// Renderer (In isolated world id1004)
window.electron.doThing()
API 函数
¥API Functions
通过 contextBridge
绑定的 Function
值通过 Electron 进行代理,以确保上下文保持隔离。这导致了我们在下面概述的一些关键限制。
¥Function
values that you bind through the contextBridge
are proxied through Electron to ensure that contexts remain isolated. This
results in some key limitations that we've outlined below.
参数/错误/返回类型支持
¥Parameter / Error / Return Type support
由于参数、错误和返回值在通过网桥发送时会被复制,因此只能使用某些类型。在较高的层次上,如果你想要使用的类型可以序列化和反序列化为同一个对象,那么它就可以工作。为了完整起见,下面包含了类型支持表:
¥Because parameters, errors and return values are copied when they are sent over the bridge, there are only certain types that can be used. At a high level, if the type you want to use can be serialized and deserialized into the same object it will work. A table of type support has been included below for completeness:
类型 | 复杂 | 参数支持 | 返回值支持 | 局限性 |
---|---|---|---|---|
string | 简单的 | ✅ | ✅ | 不适用 |
number | 简单的 | ✅ | ✅ | 不适用 |
boolean | 简单的 | ✅ | ✅ | 不适用 |
Object | 复杂的 | ✅ | ✅ | 必须仅支持使用此表中的 "简单的" 类型的键。该表中必须支持值。原型修改被删除。发送自定义类将复制值,但不会复制原型。 |
Array | 复杂的 | ✅ | ✅ | 与 Object 型相同的限制 |
Error | 复杂的 | ✅ | ✅ | 抛出的错误也会被复制,这可能会导致错误的消息和堆栈跟踪由于在不同的上下文中抛出而略有变化,以及错误对象 会迷路 上的任何自定义属性 |
Promise | 复杂的 | ✅ | ✅ | 不适用 |
Function | 复杂的 | ✅ | ✅ | 原型修改被删除。发送类或构造函数将不起作用。 |
可克隆类型 | 简单的 | ✅ | ✅ | 请参阅有关可克隆类型的链接文档 |
Element | 复杂的 | ✅ | ✅ | 原型修改被删除。发送自定义元素将不起作用。 |
Blob | 复杂的 | ✅ | ✅ | 不适用 |
Symbol | 不适用 | ❌ | ❌ | 符号不能跨上下文复制,因此它们被删除 |
如果你关心的类型不在上表中,则可能不支持。
¥If the type you care about is not in the above table, it is probably not supported.
公开 ipcRenderer
¥Exposing ipcRenderer
尝试通过 contextBridge
将整个 ipcRenderer
模块作为对象发送将导致桥接接收端出现空对象。通过 ipcRenderer
完整发送可以让任何代码发送任何消息,这是一种安全手段。要通过 ipcRenderer
进行交互,请提供如下所示的安全封装器:
¥Attempting to send the entire ipcRenderer
module as an object over the contextBridge
will result in
an empty object on the receiving side of the bridge. Sending over ipcRenderer
in full can let any
code send any message, which is a security footgun. To interact through ipcRenderer
, provide a safe wrapper
like below:
// Preload (Isolated World)
contextBridge.exposeInMainWorld('electron', {
onMyEventName: (callback) => ipcRenderer.on('MyEventName', (e, ...args) => callback(args))
})
// Renderer (Main World)
window.electron.onMyEventName(data => { /* ... */ })
公开节点全局符号
¥Exposing Node Global Symbols
预加载脚本可以使用 contextBridge
来让渲染器访问 Node API。上述支持类型表也适用于你通过 contextBridge
公开的 Node API。请注意,许多 Node API 授予对本地系统资源的访问权限。对于向不受信任的远程内容公开哪些全局变量和 API,请务必小心。
¥The contextBridge
can be used by the preload script to give your renderer access to Node APIs.
The table of supported types described above also applies to Node APIs that you expose through contextBridge
.
Please note that many Node APIs grant access to local system resources.
Be very cautious about which globals and APIs you expose to untrusted remote content.
const { contextBridge } = require('electron')
const crypto = require('node:crypto')
contextBridge.exposeInMainWorld('nodeCrypto', {
sha256sum (data) {
const hash = crypto.createHash('sha256')
hash.update(data)
return hash.digest('hex')
}
})