contextBridge
History
| Version(s) | Changes |
|---|---|
None |
|
Cree un puente seguro, bidireccional y sincrónico a través de contextos aislados
Process: Renderer
A continuación se muestra un ejemplo de exponer una API a un renderer desde un script de precarga aislado:
// Preload (Isolated World)
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
// Renderer (Main World)
window.electron.doThing()
Glosario
Main World
El "Main World" es el contexto de JavaScript que corre tu código renderer principal. Por defecto, la página que cargas en el tu renderer ejecuta código en este mundo.
Mundo aislado
Cuando contextIsolation está activado en tu webPreferences (este es el comportamiento por defecto desde Electron 12.0.0), tus scripts preload corren en un "Mundo aislado". You can read more about context isolation and what it affects in the security docs.
Métodos
El módulo contextBridge tiene los siguientes métodos:
contextBridge.exposeInMainWorld(apiKey, api)
apiKeystring - La clave para inyectar la API en la ventanawindow. La API será accesible enwindow[apiKey].apiany - Tu API más información sobre qué puede ser esta API y como funciona esta disponible a continuación.
contextBridge.exposeInIsolatedWorld(worldId, apiKey, api)
worldIdInteger - The ID of the world to inject the API into.0is the default world,999is the world used by Electron'scontextIsolationfeature. Using 999 would expose the object for preload context. We recommend using 1000+ while creating isolated world.apiKeystring - La clave para inyectar la API en la ventanawindow. La API será accesible enwindow[apiKey].apiany - Tu API más información sobre qué puede ser esta API y como funciona esta disponible a continuación.
contextBridge.executeInMainWorld(executionScript) Experimental
- Objeto
executionScriptfunc(...args: any[]) => any - A JavaScript function to execute. This function will be serialized which means that any bound parameters and execution context will be lost.argsany[] (optional) - An array of arguments to pass to the provided function. These arguments will be copied between worlds in accordance with the table of supported types.
Returns any - A copy of the resulting value from executing the function in the main world. Refer to the table on how values are copied between worlds.
Uso
API
La api proveeida a exposeInMainWorld debe ser una Function, string, number, Array, boolean, o un objeto cuya llaves son strings y los valores son una Function, string, number, Array, boolean, u otro objeto anidado que cumpa con las mismas condiciones.
Los valores Function se transfieren a otro contexto y todos los demás valores son copiados y congedados. Cualquier dato / primitivos enviado en la API se vuelve inmutable y las actualizaciones de una lado del puente no resulta en una actualización en el otro lado.
A continuación se muestra un ejemplo de una API compleja:
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
})
}
}
}
}
)
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()
Funciones API
Los valores de Function que enlazas a través de contextBridge son proxyados a través de Electron para asegurar que los contextos permanezcan aislados. Esto da como resultado algunas limitaciones claves que hemos descrito a continuación.
Parámetro / Error / Tipo de Retorno soportado
Dado que los parámetros, errores y valores de retorno son copiados cuando son enviados sobre el puente, solo hay ciertos tipos que pueden ser usados. En un nivel alto, si el tipo que desea usar se puede serializar y deserializar en el mismo objeto, funcionará. A continuación, se incluye una tabla de soporte de tipo para que esté completa:
| Tipo | Complejidad | Soporte de parámetros | Valor de Retorno Soportado | Limitaciones |
|---|---|---|---|---|
string | Simple | ✅ | ✅ | N/A |
number | Simple | ✅ | ✅ | N/A |
booleano | Simple | ✅ | ✅ | N/A |
Object | Complejo | ✅ | ✅ | Las llaves deben ser soportadas usando solo los tipos "Simple" en esta tabla. Los valores deben ser soportadas en esta tabla. Las modificaciones del prototipo se eliminan. Enviar clases personalizadas copiará valores pero no el prototipo. |
Array | Complejo | ✅ | ✅ | Mismas limitaciones para el tipo Object |
Error | Complejo | ✅ | ✅ | Errors that are thrown are also copied, this can result in the message and stack trace of the error changing slightly due to being thrown in a different context, and any custom properties on the Error object will be lost |
Promise | Complejo | ✅ | ✅ | N/A |
Function | Complejo | ✅ | ✅ | Las modificaciones del prototipo se eliminan. Enviar clases o constructores no funcionará. |
| Tipos Clonables | Simple | ✅ | ✅ | Veer el documento vinculado en tipos clonables |
Elemento | Complejo | ✅ | ✅ | Las modificaciones del prototipo se eliminan. Enviar elementos personalizados no funcionará. |
Blob | Complejo | ✅ | ✅ | N/A |
Símbolo | N/A | ❌ | ❌ | Los Symbols no pueden ser copiados a través de contextos así que son eliminados |
Si el tipo que te interesa no está en la tabla anterior, probablemente no esté soportado.
Exposing 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 => { /* ... */ })
Exponer Global Symbols de Node
El contextBridge puede ser utilizado por el script de precarga para dar acceso al renderizador a las APIs de Node. La tabla de tipos soportados descrita anteriormente aplica también a las APIs de Node que expongas a través de contextBridge. Tenga en cuenta que muchas APIs de Nodo conceden acceso a los recursos del sistema local. Se muy cauteloso sobre que APIs y globales expones a contenido remoto que no es de confianza.
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')
}
})