contextBridge
History
Version(s) | Changes |
---|---|
None |
|
分離されたコンテキスト間に、安全、双方向で同期されたブリッジを作成します
プロセス: Renderer
分離されたプリロードスクリプトから 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
スクリプトは "隔離ワールド" で実行されます。 コンテキスト分離とその影響の詳細については、BrowserWindow のドキュメントを参照してください。
メソッド
contextBridge
モジュールには以下のメソッドがあります。
contextBridge.exposeInMainWorld(apiKey, api)
apiKey
string -window
に API を注入するキー。 その API にはwindow[apiKey]
でアクセスできます。api
Record - あなたの API です。この詳細と動作については下記を参照してください。
contextBridge.exposeInIsolatedWorld(worldId, apiKey, api)
worldId
Integer - API を注入するワールドの ID です。0
はデフォルトのワールドで、999
は Electron のcontextIsolation
機能で使用されるワールドです。 999 を使用すると、プリロードコンテキストのオブジェクトが公開されます。 隔離ワールドを作成する際には 1000 以上の使用を推奨します。apiKey
string -window
に API を注入するキー。 その API にはwindow[apiKey]
でアクセスできます。api
Record - あなたの API です。この詳細と動作については下記を参照してください。
使い方
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 | 複雑 | ✅ | ✅ | なし |
Symbol | なし | ❌ | ❌ | Symbol はコンテキスト間でコピーできないため、削除されます |
関心のある型が上記の表にない場合、それはおそらくサポートされていません。
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 => { /* ... */ })
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')
}
})