contentElectronでcontextBridgeによる安全なIPC通信JavaScriptNode.jsxssElectronはじめにElectronの情報って、検索すると沢山出てくるのに、ところどころみな違っていて見極めが難しいですよね。私自身よくわかっていないですが、調べた情報を共有します。現時点での結論として、セキュアなIPC通信にはcontextBridgeを使おう、ということらしいです。いえ、Electronの状況はversionによってかなり変わるようなので、以下の際内容には注意してください。こちらで検証した時点でのElectronのversionは7.1.9です。Electronにおけるセキュアな設計とは前提として、Electronでは、メインプロセスと、webページ画面として動くレンダラープロセスが立ち上がります。./main.jsその中でBrowserWindow.loadURL()関数などで読み込まれたhtmlがレンダラープロセス上で起動します(今回はindex.htmlとします)。index.html上で読み込まれたjsファイルもレンダラープロセス上で実行されます。たたき台として、以下のようなコードが最小コードとしましょう。</script></html>ここで、昔のversionのElectronではレンダラープロセス上でもファイル読み書きなどのnodeの便利なメソッドが使えたわけですが、最近はdefaultでは使えなくなっているそうです。index.html"のようなエラーメッセージが出ます。ファイル読み書きなどのnodeの機能はメインプロセス上だけでやろう、という方針を取るにしても、レンダラープロセスからの信号や情報をメインプロセスへ伝える手段がいるわけです。プロセス間の通信はIPC通信としてElectronのAPIが用意されているものの、最低限レンダラープロセス上での通信処理を司るipcRendererが欲しくなります(公式docs)。requireが使えないのでそれすら取得できません。検索して出てくる情報は以下のようなものが多いです。trueにすればよい。falseのままにすべし。その代わりpreloadを使おう。preload内で準備したオブジェクトや関数をレンダラープロセスのjsで使うためには、(globalや)windowの変数に追加することでインスタンスを渡そう。あるversion以降、プロセス間でwindowが同一のオブジェクトではなくなった。よって受け渡しできない。trueのままにしよう。巡り巡って、どうやら、7番の方法で解決みたいですが、それ以前の手立ても含めて以下にまとめていきます。truenodeIntegrationというのは、メインプロセスでウィンドウを生成するとき位のオプションで指定します。先のmain.jsにおいて、BrowserWindowの生成部分のコードを以下の様に書き替えます。//これだけで、レンダラープロセスでrequire関数が使えるようになります。Content-Security-Policy)"というwarningメッセージがでてきて、なにやら危ないようです。XSSの危険が大きいということで、あまりお勧めできないようです。falseとしながら、レンダラープロセスでせめてIPC通信だけでもするにはどうするのか。そこで出てくるのがpreloadで追加jsを先行して読ませる方法です。読ませるjsをpreload.jsとします。このpreload.jsにおいてはnode.jsの機能、つまりrequire関数が使えるので、これをグローバルなオブジェクト変数として記録します。それをレンダラープロセスから使うということになります。コードで書くと、次のようになります。</script></html>まず、main.jsでは、BrowserWindowの生成のoptionにpreloadとcontextIsolationの項目を追加しています。IPCメッセージの受信部としてipcMain.onを設定しています。preload.jsではrequireが利用できるので、グローバル変数としてwindow.MyIPCSend(msg)関数を追加し、その中でipcRendererを使ったメッセージ送信の機能を持たせます。ここからメインプロセスのipcMain.onへメッセージを送ります。index.htmlではボタンを押したときにwindow.MyIPCSend(msg)関数を呼び出します。これはpreload.jsで定義したものですが、グローバルなwindowオブジェクトに保持されているので使えるようです。このような形でIPCメッセージだけでもやり取りできれば、それで必要な情報を送り、node関連の機能を使った処理は全てメインプロセスへ押し付けてしまうこともできるでしょう。falseが必要です。trueとなったようです。セキュアにするには、ここもtrueがよいと。trueとすると、preload.jsから呼び出したwindowと、index.htmlで呼び出すwindowのインスタンスが別物になってしまいます。よって、window.MyIPCSend(msg)関数をindex.htmlから呼び出しても、定義されていない旨のエラーメッセージが出ます。APIがあるそうです1。これはElectronで公式に提案されたセキュアなプロセス間通信の実現のためのAPIだそうです(これを見つけた時は、嬉しくて叫んじゃいました)。コードは次のようになります。trueに変えただけです。大きく変わったのはpreload.jsです。electronからオブジェクトcontextBridgeを取り出し、exposeInMainWorld()によってグローバルな関数send()を登録しています。ここで登録した関数は、レンダラープロセスのindex.htmlの中からもwindow.api.send()として呼び出すことができます。注意点contextBridgeはとっても良さそうなAPIですが、Electronのドキュメント3には次のように書かれています。release."一応、私の環境のversion7.1.9では使えていますが、いつから使えるようになったのかはちょっと不明なので、気を付けてください。感想HTML+Javascriptでブラウザ上だけでほぼ動くものを作ってしまえば、パッケージングはElectronですぐにできると思っていた時期が僕にもありました。この記事がだれかの参考になれば幸いです。いえ、なにぶんJavascriptはライト勢なので、間違いもたくさんありそう。ご指摘いただければ大変嬉しいです。レンダラープロセスでの受信編も投稿しました。upLoginユーザーは見つかりませんでした。