contextBridge
History
| Version(s) | Changes |
|---|---|
None |
|
分離されたコンテキスト間に、安全、双方向で同期されたブリッジを作成します
プロセス: レンダラー
分離されたプリロードスクリプトから API をレンダラーに公開する例を以下に示します。
// プリロード (隔離ワールド)
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
// レンダラー (メインワールド)
window.electron.doThing()
用語集
メインワールド
"メインワールド" は、メインレンダラーコードが実行される JavaScript コンテキストです。 デフォルトでは、レンダラーでロードしたページはこのワールドでコードを実行します。
隔離ワールド
webPreferences で contextIsolation が有効 (これは Electron 12.0.0 からの既定の動作) になっている場合、preload スクリプトは "隔離ワールド" で実行されます。 コンテキスト分離とその効果の詳細については、セキュリティ のドキュメントを参照してください。
メソッド
contextBridge モジュールには以下のメソッドがあります。
contextBridge.exposeInMainWorld(apiKey, api)
apiKeystring -windowに API を注入するキー。 その API にはwindow[apiKey]でアクセスできます。apiRecord - あなたの API です。この詳細と動作については下記を参照してください。
contextBridge.exposeInIsolatedWorld(worldId, apiKey, api)
worldIdInteger - API を注入するワールドの ID です。0はデフォルトのワールドで、999は Electron のcontextIsolation機能で使用されるワールドです。 999 を使用すると、プリロードコンテキストのオブジェクトが公開されます。 隔離ワールドを作成する際には 1000 以上の使用を推奨します。apiKeystring -windowに API を注入するキー。 その API にはwindow[apiKey]でアクセスできます。apiRecord - あなたの API です。この詳細と動作については下記を参照してください。
contextBridge.executeInMainWorld(executionScript) 実験的
executionScriptオブジェクトfunc(...args: any[]) => any - 実行する JavaScript 関数。 この関数はシリアル化され、バインドされたパラメータと実行コンテキストは失われます。argsany[] (任意) - 指定された関数に渡す引数の配列。 これらの引数は 引数 / エラー / 戻り値型のサポート に従って、コンテキスト間でコピーされます。
戻り値 any - メインコンテキストで関数を実行した結果の値のコピー。 コンテキスト間の値のコピー方法については、表を参照してください。
使い方
API
exposeInMainWorld に指定する api は、Function、string、number、Array、boolean、または文字列のキーで Function、string、number、Array、boolean、同じ条件を満たすオブジェクトのいずれかの値の、入れ子でなければなりません。
Function 値は他のコンテキストへプロキシされ、他のすべての値は コピー か 凍結 されます。 API で送信されるデータ/プリミティブはイミュータブルであり、ブリッジの一方で更新しても他方のものは更新されません。
複雑な API の例を以下に示します。
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 の例を以下に示します。
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInIsolatedWorld(
1004,
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
// レンダラー (ワールド ID 1004 で隔離されています)
window.electron.doThing()
API 関数
contextBridge を介してバインドした Function 値は、コンテキストが分離されたままになるように Electron を介してプロキシされます。 これにより、以下に概説するいくつかの重要な制限が生じます。
引数 / エラー / 戻り値型のサポート
引数、エラー、戻り値は、ブリッジを介して送信されるときに コピー されるため、使用できるのは特定の型のみです。 高水準なものは、使用したい型をシリアライズおよびデシリアライズして、同じように動作するオブジェクトにできます。 以下の型サポートの表に全てが載っています。
| 種類 | 複雑さ | 引数サポート | 戻り値サポート | 制限事項 |
|---|---|---|---|---|
文字列型 | 単純 | ✅ | ✅ | なし |
number | 単純 | ✅ | ✅ | なし |
boolean | 単純 | ✅ | ✅ | なし |
Object | 複雑 | ✅ | ✅ | キーにはこの表の "単純" な型のみの使用をサポートしています。 値にはこの表のものをサポートしています。 プロトタイプの変更は削除されます。 カスタムクラスを送信すると、値はコピーされますが、プロトタイプはコピーされません。 |
Array | 複雑 | ✅ | ✅ | 制限は Object 型と同じです |
エラー | 複雑 | ✅ | ✅ | 送出された Error もコピーされるため、異なるコンテキストで投げられたためにエラーのメッセージやスタックトレースが少し変化することがあります。また、Error オブジェクトのカスタムプロパティは 失われます。 |
Promise | 複雑 | ✅ | ✅ | なし |
Function | 複雑 | ✅ | ✅ | プロトタイプの変更は削除されます。 クラスまたはコンストラクターを送信しても動作しません。 |
| 複製可能型 | 単純 | ✅ | ✅ | 複製可能型に関してはリンクのドキュメントを参照してください |
Element | 複雑 | ✅ | ✅ | プロトタイプの変更は削除されます。 カスタム要素の送信は動作しません。 |
Blob | 複雑 | ✅ | ✅ | なし |
VideoFrame | 複雑 | ✅ | ✅ | なし |
Symbol | なし | ❌ | ❌ | Symbol はコンテキスト間でコピーできないため、削除されます |
関心のある型が上記の表にない場合、それはおそらくサポートされていません。
ipcRenderer の露出
ipcRenderer モジュール全体をオブジェクトとして contextBridge 経由で送信しようとすると、ブリッジの受信側に空のオブジェクトを生成します。 ipcRenderer 全体を送信すると、どのコードでも任意のメッセージを送信できるようになり、セキュリティの大きな穴になります。 ipcRenderer を介して操作する際は、以下のように安全なラッパを提供してください。
// プリロード (隔離されたワールド)
contextBridge.exposeInMainWorld('electron', {
onMyEventName: (callback) => ipcRenderer.on('MyEventName', (e, ...args) => callback(args))
})
// レンダラー (メインワールド)
window.electron.onMyEventName(data => { /* ... */ })
Node のグローバルシンボルの公開
contextBridge はプリロードスクリプトで使用でき、レンダラーが Node API へアクセスできるようにします。 上記のサポート型の表は、 contextBridge を介して公開する Node API にも適用されます。 注意として、Node API の多くはローカルシステムのリソースへのアクセスを許してしまいます。 信頼できない外部コンテンツにおいては、公開するグローバルや API について注意が必要です。
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')
}
})