本記事では、ElectronのVer.12以降でセキュアにモジュールを使用する際に躓きがちな「ContextBridge.ipcMainWorld」と「ipcRenderer.invoke」について解説します!
さらに、具体例にSlackAPIによるメッセージの送信を使用することで、一緒に使い方を覚えてしまおうという魂胆です!
(注意)
非プログラマーの独学&初投稿になりますのでどうぞお手柔らかに。
ここ直すといいよ!というアドバイスいただけたら幸いです!
##目次
- 作成する機能
- セキュアにモジュールを使用するには
- 実際にやってみる
- SlackAPIでメッセージ送信
- まとめ
1.作成する機能
「ボタンをクリックしたら、Slackにあらかじめ決められたメッセージ(かめはめ波)を飛ばす」だけの非常にシンプルな機能を作成します。
という建前のもと、デバックの取り方わからなかったので、代わりにAPIでメッセージを投げます(笑)
electronについてはこちら
2.セキュアにモジュールを使用するには
electronでは、以前からXSSの危険性が指摘されています。
バージョン更新のたびにデフォルトの設定が変更になるなど、
私を含め初心者にとってややこしい状況かと。
まずは公式ドキュメントを見てみましょう。また併せて日本語でも検索します。
それぞれ共通するキーワードをピックアップします。
- preload.js
- ContextBridge.ipcMainWorld
- ipcRenderer.invoke
- ipcMain.handle
これらを組み合わせることにより、従来より指摘されていたXSSの危険性を回避しつつ、モジュールを使用することができるっぽいですね。
3.実際にやってみる
まずはじめに、画面となるHTMLを準備します。
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta content="width=device-width" name="viewport">
<title>テスト</title>
</head>
<body>
<p><input type="button" value="かめはめ波" id=Button></p>
<script src="./renderer.js"></script>
</body>
</html>
rendererプロセス側から「window.任意のAPIキー.任意のAPI名(引数)」という形でpreload.jsの処理を呼び出します。
const button = document.getElementById("Button");
button.addEventListener('click',async () => {
const result = await window.electron.sendToMain("かめはめ波");
console.log(result);
})
次にpreload.jsでは、「contextBridge.exposeInMainWorld('任意のAPIキー', {任意のAPI名:処理内容})」という形で窓口を用意します。
この時、処理内容には「ipcRenderer.invoke('任意の名前', 引数)」を記述し、mainプロセスの処理を呼びに行きます。
const {contextBridge,ipcRenderer} = require("electron");
contextBridge.exposeInMainWorld(
'electron', {
sendToMain: async (skill) => {
const result = await ipcRenderer.invoke('invoke-test', skill) ;
return result;
}
})
最後にmainプロセスでは、preload.jsに対応する「ipcMain.handle('任意の名前',async(event,data) => { 処理内容...}」と記述し、呼び出しの受け取りと処理の実行を行います。
ipcMain.handle('invoke-test', async(event,data) => {
const Result = await sendMessageSlack();
return Result
});
const sendMessageSlack = async() => {
//処理
}
SlackAPIでメッセージ送信
SlackのApiの使用に関してはこちら
上記のMainプロセスで呼び出される関数を以下のように記述します。TokenやChannel名は態々外に出さなくてもいいかもですが、後から見てわかりやすいかなと思ってconstしてます。
const { WebClient, LogLevel } = require("@slack/web-api");
const apiToken = "Slackの設定で取得したApiToken";
const chatGroup = "任意のチャンネル名";
const client = new WebClient(apiToken, {logLevel: LogLevel.DEBUG});
const sendMessageSlack = async(text) => {
try {
const result = await client.chat.postMessage({
token: apiToken,
channel: chatGroup,
text: text
});
console.log(result);
}
catch (error) {
console.error(err);
}
}
まとめ
その他の参考記事
所感
初心者にとって、async/awaitが入れ子になっている上に、他では使わない概念の理解やMethodの使用が求められ、なかなか大変でした。
すでに同様の内容を書かれている記事も見ましたが、うまく動かなかったり、
かゆいところに届かなかったりで、自分で試行錯誤して何とかたどり着きました。
もし同じような境遇の方がこれをタタキにして、やりたかったことができると👍