ZoomSDKを使ってブラウザからZoomミーティングに参加する仕組みを作ってみた

# はじめに
この記事は、[「Qiita Engineer Festa 2022」](https://qiita.com/official-campaigns/engineer-festa/2022)に参加するために書きました
「Zoomミーティングに参加する際、アプリを起動せずブラウザから入れたら便利かもしれない」と思ったので、ZoomSDKを使ってブラウザ（Chrome）からZoomを立ち上げて参加できる仕組みを作りました。

# 作ったもの
1. Chrome拡張機能からZoom起動をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016468/78f91bc6-7dc1-c7b1-a9cb-2c2e5b59962e.png)
2. 別タブでZoomSDKが起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016468/c467862f-8de5-63ed-64be-5dd556161f81.png)
3. ZoomミーティングのID・パスワードを入れてログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016468/2a523c12-db63-d979-dc6b-ac5191529c5a.png)
4. Zoomミーティング参加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016468/98b8f9d4-3275-93a6-72f6-120a0c4638b2.png)
5. ミーティング終了後、Zoom終了ボタンを押してSDK停止
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016468/b3092e5a-7a14-acab-9b3c-5b7449ebd50d.png)

**アプリを起動せずにZoomミーティングに参加できる！**

# 手順①　SDK実装
Zoomが公式で投稿しているQiita記事が非常に丁寧で分かりやすいです。
初めてSDKを触りましたが、以下の記事を参考に簡単に実装（Client view）することができました。

https://qiita.com/yosuke-sawamura/items/de69e73e47335cd61d68

https://qiita.com/yosuke-sawamura/items/df6eb3b4bc2f11ba281f

また調べてみると、Quick installというGit cloneして実装するやり方もあるようです。
以下の記事を参考に試してみましたが、こちらも簡単に実装できました。

https://qiita.com/youtoy/items/7496f723ead1832bf825

# ここから先の説明について
ここから先、本来やりたいことに対して遠回りな内容になっているかもしれません。
当初、**Chrome拡張クリック→サーバー起動→SDK起動**　をやりたいと思ってました。
しかし、ブラウザからサーバーを起動する方法が調べても分かりませんでした。
ブラウザから起動すること（ターミナルを操作しない）に拘っていたので、
なんとか実現できないか試して行き着いたのが、以下の方法です。

# 手順②　バッチファイル作成
まずはターミナルを操作せずにサーバーを起動する方法として、バッチファイルを作ります。
ファイルをダブルクリックすれば、ターミナルで以下のコマンドを打つのと同じことをできます。
こちらのコマンドについては、上であげたZoomの公式Qiitaに書かれています。

```javascript:サーバー起動
node index.js
```

とりあえず任意の場所でバッチファイルを作成します。
バッチファイルの拡張子は **.commnad** です。
作り方の詳細は以下の記事が参考になります。

https://qiita.com/nekotanku/items/155f91779b83ae8b0ef5

ファイルを作ったら以下のように記述します。
記述後、ファイルをダブルクリックしてサーバー・SDK起動まで確認できたらOKです。

```bat:バッチの中身
#SDKを実装したフォルダに移動
cd "SDKを実行するフォルダパス"
#SDKを起動させるタブを開く
open http://localhost:4000/
#サーバー起動
node index.js
```

バッチファイルを実行します。
バッチファイル名は、zoom.commandにしました。
シェルはfishを使ってますが、bashかzshを使っていれば置き換えて実行可能です。

```bat:バッチファイル実行
fish zoom.command
```


「実行権限がありません」とエラーが出たら、
次のコマンドでをターミナルに打って解決できます。
以下記事を参考にしました。

```
chmod u+x
```
https://rikoubou.hatenablog.com/entry/2019/09/27/114255

# 手順③　ブラウザからバッチファイル実行
ブラウザから、バッチファイルを実行するための処理を行なっていきます。
以下の記事を参考にしました。

https://flat-leon.hatenablog.com/entry/launch_program_from_html

大まかにですが、以下のような流れで実装します。
- Script Editor.appを使ってプログラム作成
- URLスキーム経由でプログラム起動

上記記事の説明に沿って、プログラムの起動が確認できたら、以下のようにアドレスバーに入力して、先ほど作ったバッチファイルを実行します。
このとき実行するバッチファイルは、**ホームディレクトリ** に移しておく必要があります。

```
#XXXXは自分で作った名前に変更
XXXX://XXXX.command
```

# 手順④　Chrome拡張機能作成
ここまででブラウザから、ZoomSDKを起動できるようになりましたが、
これだとアドレスバーに手入力をしなくてはいけません。
Chrome拡張機能を作り、クリック操作で実行できるようにします。
以下の記事を参考にしました。非常に分かりやすいので、こちらをご参照ください。

https://original-game.com/how-to-make-chrome-extensions/

アドバイスバーに入力をしたいので、まず以下のようなhtmlを書きました。しかし、このやり方はうまくいきません。

```json:manifest.josn
{
  "name": "ZoomSDK",
  "manifest_version": 3,
  "version": "0.2",
  "permissions": [
    "activeTab",
    "scripting"
  ],
  "action": {
    "default_icon": {
      "16": "image/icon.png"
    },
    "default_popup": "index.html"
  }
}
```
```html:index.html
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <title>ZoomSDK</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <h2>ZoomSDK</h2>
  <button type="button" onclick="window.open('XXXX://fish XXXX.command')">Zoom起動</button>
</body>

</html>
```

この状態で拡張機能をクリックして表示される「Zoom起動」をクリックしても、以下のようなエラーが出てしまいます。
エラーの内容は **chrome://extensions/** で開く、拡張機能のページで確認できます。

```
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'wasm-unsafe-eval'". Either the 'unsafe-inline' keyword, a hash ('XXXXX'), or a nonce ('nonce-...') is required to enable inline execution.
```

調べてみると、Chromeアプリのページではインラインスクリプトを使うことができないようです。
以下を記事を参考に、Javascriptファイル側にDOMContentLoadedを定義して解決しました。

https://omohikane.com/chrome_extension_content_security_policy_directive/

https://developer.chrome.com/docs/apps/contentSecurityPolicy/

ちなみに、文字化けの読み方を知らなかったので調べました。

https://blog.codecamp.jp/html-special-character

以下のようなJavascriptファイルを新たに作り、htmlファイルを修正しました。

```javascript:csp.js
document.addEventListener('DOMContentLoaded', function () {
  document.querySelector('#btnStart').addEventListener('click', function () {
    window.location.assign("XXXX://fish XXXX.command")
  });
});
```
```html:index.html
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <title>ZoomSDK</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <h2>ZoomSDK</h2>
  <button type="button" id="btnStart">Zoom起動</button>
  <script src="/csp.js" charset="utf-8">
  </script>
</body>

</html>
```

これで拡張機能をクリック、「Zoom起動」をクリックしてもエラーはでません。「アプリケーションを開く許可を求めています」という確認ダイアログが出てきます。しかし、拡張機能が右上にありその直下に確認ダイアログが出てくるため、「はい」の選択肢がはみ出て押せない。。スクショを撮り忘れてしまったため、以下イメージ図です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016468/d264a2c9-5225-771d-9897-94833de9b773.png)

「こんなところで、、」という気持ちを抑えつつ、以下の記事を参考に確認ダイアログが出ないように設定。ターミナルにコマンドを打ちます。

https://owky.github.io/blog/2022/01/09/mac-chrome-url-allow-list.html

```
defaults write com.google.Chrome URLAllowlist -array "XXXX（設定したプログラム名）://*"
```

今回の実装では、Zoom起動・Zoom終了の２つでこの設定をしました。
複数個の登録をする場合はこちらが参考になります。

https://www.web-dev-qa-db-ja.com/ja/windows-10/%E7%84%A1%E5%8A%B9%E3%81%AB%E3%81%99%E3%82%8Bchrome%E6%AF%8E%E5%9B%9E%E5%A4%96%E9%83%A8%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E9%96%8B%E3%81%8F%E3%81%9F%E3%82%81%E3%81%AE%E7%A2%BA%E8%AA%8D%E3%82%92%E6%B1%82%E3%82%81%E3%82%8B%E3%81%AB%E3%81%AF/944609907/


```
defaults write com.google.Chrome URLWhitelist -array 'XXXXX1://*' 'XXXXX2://*' 'XXXXX3://*'
```

ここまでで、ターミナルもZoomアプリも操作することなく、ブラウザからZoomSDKを起動して、Zoomミーティングに入れるようになりました！

# 手順⑤　Zoom終了・サーバー停止
上記のZoomSDK起動までと同じことをして、バッチファイルの中身だけ変えました。以下のように記述して、拡張機能から「Zoom終了」を押せばサーバーが停止することができます。

```bat:Zoom終了のバッチファイル
killall node index.js
exit
```

# おわりに
色々調べてみたが、ブラウザからサーバ起動することは結局できませんでした。。
もしご存知の方いらしたら、コメントで教えていただけるとありがたいです。。
また今回Qiita記事をあげるのは初めてでしたが、この記事を各過程で学びが多くありました。
今後は、日常で学んだことの棚卸し含め、定期的にアウトプットしていこうと思います。
ここまで読んでくださった方、拙い文章だったかと思いますが最後までありがとうございました。