メインコンテンツへスキップ

contextBridge

履歴

分離されたコンテキスト間で安全な双方向同期ブリッジを作成します

プロセス: レンダラー

分離されたプリロードスクリプトからレンダラーにAPIを公開する例を以下に示します

// Preload (Isolated World)
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
// Renderer (Main World)

window.electron.doThing()

用語集

メインワールド

「メインワールド」は、メインレンダラーコードが実行されるJavaScriptコンテキストです。デフォルトでは、レンダラーにロードしたページはこのワールドでコードを実行します。

分離されたワールド

webPreferencescontextIsolationが有効になっている場合(Electron 12.0.0以降のデフォルトの動作です)、preloadスクリプトは「分離されたワールド」で実行されます。コンテキストの分離とその影響について詳しくは、セキュリティドキュメントをご覧ください。

メソッド

contextBridgeモジュールには、以下のメソッドがあります

contextBridge.exposeInMainWorld(apiKey, api)

  • apiKey 文字列 - APIをwindowに挿入するキー。APIはwindow[apiKey]でアクセスできます。
  • api 任意 - API。このAPIの内容と動作方法については、以下をご覧ください。

contextBridge.exposeInIsolatedWorld(worldId, apiKey, api)

  • worldId 整数 - APIを挿入するワールドのID。0はデフォルトのワールド、999はElectronのcontextIsolation機能で使用されるワールドです。999を使用すると、プリロードコンテキストのオブジェクトが公開されます。分離されたワールドを作成する際は、1000以上を使用することをお勧めします。
  • apiKey 文字列 - APIをwindowに挿入するキー。APIはwindow[apiKey]でアクセスできます。
  • api 任意 - API。このAPIの内容と動作方法については、以下をご覧ください。

使用方法

API

exposeInMainWorldに提供されるapiは、FunctionstringnumberArrayboolean、またはキーが文字列で値がFunctionstringnumberArrayboolean、または同じ条件を満たす別のネストされたオブジェクトであるオブジェクトでなければなりません。

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')
}
)
// Renderer (In isolated world id1004)

window.electron.doThing()

API関数

contextBridgeを介してバインドするFunction値は、コンテキストが分離された状態を維持するためにElectronを介してプロキシされます。これにより、以下に概説するいくつかの重要な制限事項が生じます。

パラメータ/エラー/戻り値の型のサポート

パラメータ、エラー、戻り値はブリッジを介して送信されるときに**コピー**されるため、使用できる型は限られています。大まかに言うと、使用したい型が同じオブジェクトにシリアライズおよびデシリアライズできる場合は、機能します。完全を期すために、型のサポートの表を以下に示します

複雑度パラメータサポート戻り値サポート制限事項
string単純N/A
number単純N/A
boolean単純N/A
Object複合キーは、この表の「単純」型のみを使用してサポートする必要があります。値はこの表でサポートされている必要があります。プロトタイプの変更は破棄されます。カスタムクラスを送信すると、値はコピーされますが、プロトタイプはコピーされません。
Array複合Object型と同じ制限事項
Error複合スローされるエラーもコピーされます。これは、異なるコンテキストでスローされるため、エラーのメッセージとスタックトレースがわずかに変更される可能性があり、Errorオブジェクトのカスタムプロパティは失われます
Promise複合N/A
Function複合プロトタイプの変更は破棄されます。クラスまたはコンストラクタの送信は機能しません。
クローン可能な型単純クローン可能な型に関するリンク先のドキュメントを参照してください
Element複合プロトタイプの変更は破棄されます。カスタム要素の送信は機能しません。
Blob複合N/A
SymbolN/Aシンボルはコンテキスト間でコピーできないため、破棄されます

気になる型が上記の表にない場合は、おそらくサポートされていません。

ipcRendererの公開

ipcRendererモジュール全体をオブジェクトとしてcontextBridgeを介して送信しようとすると、ブリッジの受信側で空のオブジェクトが生成されます。ipcRendererを完全に送信すると、あらゆるコードがあらゆるメッセージを送信できるようになり、セキュリティ上の弱点になります。ipcRendererを介して対話するには、以下のような安全なラッパーを提供します

// 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')
}
})