contextBridge
History
Version(s) | Changes |
---|---|
None |
|
Crée un pont synchrone sécurisé, bidirectionnel entre des contextes isolés
Process: Renderer
Exemple d’une API exposée à un moteur de rendu à partir d’un script de preload:
// Preload (Univers Isolé)
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
// Renderer (Univers principal)
window.electron.doThing()
Glossaire
Univers principal (Main World)
« Main World » est le contexte JavaScript dans lequel votre code de rendu principal s'exécute. Par défaut, la page que vous chargez dans votre moteur de rendu exécute son code dans cet univers.
Univers isolé (Isolated World)
Votre script preload
s'exécute dans un "Isolated World" lorsque contextIsolation
est activé dans vos webPreferences
(ce qui est le comportement par défaut depuis Electron 12.0.0). You can read more about context isolation and what it affects in the security docs.
Méthodes
Le module contextBridge
possède les méthodes suivantes :
contextBridge.exposeInMainWorld(apiKey, api)
apiKey
string - Clé à utiliser pour injecter l'API dansfenêtre
. L’API sera accessible parwindow[apiKey]
.api
any- Votre API, plus d'informations sur ce que peut être cette API et son fonctionnement est disponible ci-dessous.
contextBridge.exposeInIsolatedWorld(worldId, apiKey, api)
worldId
Integer - L'ID de l'univers dans lequel injecter l'API.0
est l'univers par défaut,999
est celui utilisé par la fonctionnalitécontextIsolation
d'Electron. Utiliser 999 exposera l'objet pour le contexte du préchargement. Nous vous recommandons d’utiliser les valeurs 1000 et+ lors de la création d’un univers isolé.apiKey
string - Clé à utiliser pour injecter l'API dansfenêtre
. L’API sera accessible parwindow[apiKey]
.api
any- Votre API, plus d'informations sur ce que peut être cette API et son fonctionnement est disponible ci-dessous.
Utilisation
API
L' api
fournie à exposeInMainWorld
peut être du type Function
, string
, number
, Array
, boolean
ou un objet dont les clés sont des chaînes de caractères et les valeurs du type Function
, string
, number
, Array
, boolean
ou bien encore un autre objet imbriqué remplissant les mêmes conditions.
Les valeurs de type Function
sont "proxyfiées" vers l'autre contexte et toutes les autres valeurs sont copiées et gelées. Toutes les données ou primitives envoyées à l'API deviennent immuables et les mises à jour d'un coté ou de l'autre du contextBridge ne donnent pas lieu à une mise à jour de l'autre côté.
Exemple d’API complexe:
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
})
}
}
}
}
)
Voici ci-dessous un exemple de l'utilisation de exposeInIsolatedWorld
:
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInIsolatedWorld(
1004,
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
// Rendu (Dans l'univers isolé id1004)
window.electron.doThing()
Fonction de l'API
Les valeurs de type Function
que vous liez à travers le contextBridge
sont servies par l'intermédiaire d'Electron qui agit en tant que proxy pour s'assurer que les contextes restent isolés. Ceci entraîne certaines restrictions décrites ci-dessous.
Prise en charge des paramètres, erreurs et type de retour
Étant donné que les paramètres, erreurs et valeurs de retour sont copiés lors de leur transmission par le contextBrideg, seuls certains types peuvent être utilisés. Mais si le type que vous voulez utiliser peut être sérialisé et désérialisé dans le même objet cela fonctionnera. Une table des types supportés est incluse en complément:
Type | Complexité | Prise en charge de paramètres | Prise en charge de valeur de retour | Limitations |
---|---|---|---|---|
string | Simple | ✅ | ✅ | N/A |
number | Simple | ✅ | ✅ | N/A |
boolean | Simple | ✅ | ✅ | N/A |
Objet | Complexe | ✅ | ✅ | Les clés prises en charge ne doivent utiliser que les types "Simple" dans cette table. Les valeurs doivent être supportées dans cette table. Les modifications du prototype sont supprimées. L'envoi de classes personnalisées copiera les valeurs mais pas le prototype. |
Array | Complexe | ✅ | ✅ | Limitation identique au type Object |
Erreur | Complexe | ✅ | ✅ | Les erreurs levées sont également copiées, ce qui peut entraîner une légère modification du message et de la trace de pile de l’erreur en raison du lancement dans un contexte différent, toutes les propriétés personnalisées de l’objet Error seront également perdues |
Promise | Complexe | ✅ | ✅ | N/A |
Function | Complexe | ✅ | ✅ | Les modifications du prototype sont supprimées. L'envoi de classes ou de constructeurs ne fonctionnera pas. |
Types clonables | Simple | ✅ | ✅ | Voir le document lié sur les types clonables |
Élément | Complexe | ✅ | ✅ | Les modifications du prototype sont supprimées. L'envoi d'éléments personnalisés ne fonctionnera pas. |
Objet blob | Complexe | ✅ | ✅ | N/A |
Symbole | N/A | ❌ | ❌ | Les symboles ne peuvent pas être copiés de contexte à contexte, donc ils sont abandonnés |
Si le type qui vous intéresse n'est pas dans la table ci-dessus, il n'est probablement pas pris en charge.
Exposition de l'ipcRenderer
Toute tentative d'envoie du module ipcRenderer
entier comme un objet via le contextBridge
entraînera la réception d'un objet vide du côté récepteur du pont. L'envoie de l'ipcRenderer
dans son intégralité permettrait à n'importe quel code d'envoyer n'importe quel message et équivaudrait à se tirer une balle dans le pied. Pour interagir à travers ipcRenderer
, vous devrez alors utiliser un wrapper sûr comme ci-dessous:
// Preload (Isolated World)
contextBridge.exposeInMainWorld('electron', {
onMyEventName: (callback) => ipcRenderer.on('MyEventName', (e, ...args) => callback(args))
})
// Renderer (Main World)
window.electron.onMyEventName(data => { /* ... */ })
Exposition des symboles globaux de Node
Le contextBridge
peut être utilisé par le script de préchargement pour donner à votre moteur de rendu l'accès aux API de Node. La table des types supportés ci-dessus s'applique également aux API Node que vous exposez à travers contextBridge
. Notez bien que de nombreuses API Node accordent l'accès aux ressources du système local. Soyez donc très prudent quant aux globales et aux API que vous pourriez exposer à des contenus distants non fiables.
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')
}
})