Chrome拡張機能をmanifest v3で開発した簡易記録とハマりポイントの解消方法
Chromeの拡張機能(プラグイン)を自作で作ってみたので、色々書く。
- やってみたこと
- やった結果
- 動かせたの?
- 開発した時の環境
- ハマりポイントと解消方法の一覧
- そもそも拡張機能を作るために必要な構成や作るべきファイルがわからない
- 開発成果物のそれぞれの役割がよくわからない
- 自作したChrome拡張機能の取り込み方法がわからない
- ツールを修正した時の取り込み方法がよくわからない
- service_workerが動作しない原因がわからず、デバッグもできない
- content_scriptsに指定したcssの参照先画像(URL)にアクセスできない
- 拡張機能アイコンクリック時の動作が定義しても動かない
- service_workerで外部jsが使えない
- 自作した拡張機能用HTMLでonclick属性が動作しない
- Local Storageから読み込んだ情報が想定外にObjectになった
- JavascriptのOptional Chainがフォーマッタで崩れる
- プラグインの説明用に動画キャプチャ取りたいけど取得方法が不明
やってみたこと
やった結果
動かせたの?
- とりあえず想定するものを動かすことはできた。
- ハマりポイントも多かったので解消方法含めメモっておく。
- ハマったポイントはプラグイン作成が初だから引っかかる課題も、v3特有の課題も。
開発した時の環境
- Windows 10 Professional
- 当然だがGoogle Chromeインストール済み
- 開発環境としてVSCodeを導入済み
- npm導入済み(今回はVSCodeプラグインの強制アップデートにだけ使った)
- Dockerとdocker-composeは導入済み(拡張機能とは少し離れるが動画キャプチャ加工で使った)
ハマりポイントと解消方法の一覧
そもそも拡張機能を作るために必要な構成や作るべきファイルがわからない
- コードの例をどこから引っ張ってきて開発すればいいかすら最初はわからなかった。
- とりあえずChrome拡張機能の開発用サンプルがGithubに公開はされている。
GitHub - GoogleChrome/chrome-extensions-samples: Chrome Extensions Samples - サンプルは本当に最小構成が多いので、あくまでこれはベースであってググりまくって開発する。
- 書くものはJavascript、HTML、cssといったWebファイル相当なので、それを編集する環境があればある程度事足りる。
開発成果物のそれぞれの役割がよくわからない
ざっくり使ったものは自分の認識で取りまとめしておく。
用語 | どんなもの |
---|---|
manifest.json | 拡張機能管理の大元。これを作らないと始まらない。 拡張機能の基本情報や登録する機能、そのために使うファイルや属性を記載する。 manifestバージョンはv3への移行が進んでいて、2022年1月にmanifest v2の拡張機能は新規申請NGになった。 ※ Chromeウェブストアへの申請が止まっただけで既存ツールや自作したものは動く。 2023年には動作サポートも切られるようで、基本的にこれから作るならv3で作るべき。 |
content_scripts | 特定のWebサイトに対して追加機能を提供するための設定。任意のjsやcssファイルを追加、実行してページをカスタムしたり、ページ上の要素を取得したりすることができる。matches にURLの正規表現を指定し、合致したWebサイトのみ適用されるように設定可能。Javascript上で後述のservice_workerとやりとりすることで、Webページ上のデータを拡張機能に引き渡した処理や、クロスドメイン制約を超えたWeb通信なども実現可能。 |
service_worker | バックグラウンドに常駐する機能。というかリスナ登録で特定イベントやJavascriptからの呼び出しで発火する機能を作成、登録するイメージ。service_workerの定義をJavascriptで記載して登録する。chrome.runtime.sendMessage を通じてcontent_scriptsとデータ連携することが可能。こちらの機能はWebサイトではなくてChrome Extensionの世界で、拡張機能で許可設定した通信先であればクロスドメイン制約を受けずに通信が可能になる。*1単独機能としては何でもできるが、外部のWebページにDOM書き換え、データ取得などの干渉はできないため、そこはcontent_scriptsに任せる必要がある。 |
options_page | Chrome拡張機能のオプションを選択した際に開かれるページを設定することができる。ツールが利用する設定項目がある場合、ここでユーザに入力させてchrome.storage.local などに保存する。いい感じの設定画面になるようにHTML、css、Javascript作成してあげる(JavaScriptがchrome機能操作をするところを除くと大体通常のWeb開発と同様でいける)。 |
host_permissions | service_workerなどがここに指定したホストへのアクセス権を持つようになる。拡張機能自身はクロスドメイン制約を受けないものの、この設定がないと外部ホストへの通信処理は行えない。 また、この設定が必要なことによりユーザに拡張機能がアクセスする可能性のあるホストが明示されるようになる。 |
permissions | ローカルストレージやブックマーク、履歴などのChromeブラウザ自身が持っているデータや、各種機能、システム情報へのアクセス権を設定する。 拡張機能は何でもできるが、このpermissionが与えられていないとできない操作は多い。 参考までにローカルストレージを利用する場合は storage の定義が必要。 |
web_accessible_resources | content_scriptsなどを通じて任意の(拡張機能利用が許可された)WebページからChrome拡張機能内のファイルへアクセス権を与える場合にアクセス可能な拡張機能内の対象フォルダ・ファイルを指定する。 後述するがcontent_scriptsを適用したWebページが拡張機能の持つ画像アイコンなどを取り込む場合は必要になる。 |
自作したChrome拡張機能の取り込み方法がわからない
ツールを修正した時の取り込み方法がよくわからない
- 最初は削除して再インストールするしか無いと思っていたけどそんなことなかった。
- これもChrome拡張機能の管理ページから
更新
すればツールが1から読み込まれる。 - 自作したoptionsページの修正でも、manifestの修正でも、各種scriptの修正でもOKで全部リロードされる。
- ただし
content_scripts
が動作済のWebページは更新後にページリロードしないと正しくツールが動作しない。
service_workerが動作しない原因がわからず、デバッグもできない
content_scripts
からchrome.runtime.sendMessage
を通じてbackground.js
(service_worker)の処理を呼び出しても期待通りに動作せず、下記のようなエラーが表示される場合など。
Could not establish connection. Receiving end does not exist.`
動作しているはずのWebページ上で開発者ツールを見てもエラーログなどが出力されず原因が掴めない。
この場合、background.js
側でエラーが発生しているケースがあってログの見方は下記になる。
- 拡張機能の管理メニューを開く。
- [ビューを検証] の
Service Worker
を開く。 - Chrome開発者機能のウィンドウが表示されて、そのコンソールに
background.js
のログやエラーが表示される。 content_scripts
を動作させているページのコンソールなどには何も出力されないので注意。
content_scriptsに指定したcssの参照先画像(URL)にアクセスできない
- jQuery UIを導入して拡張機能に組み込み、拡張機能を使うWebページ上に表示しようとした時に発生。
- js, cssは
manifest.json
に指定したものをWebページ上で追加ロードできる。 - manifestには
web_accessible_resources
として格納先のパスをワイルドカード付きで指定。- 画像を
images
に格納していたら"resources": ["images/*"]
のように定義。
- 画像を
拡張機能アイコンクリック時の動作が定義しても動かない
拡張機能のアイコンクリック時にポップアップではなくて特定の処理(タブで設定ページ開くなど)をやりたい場合。
- NG:
chrome.browserAction.onClicked.addListener
をservice_workerに定義しても動作してくれない。 - NG:
chrome.pageAction.onClicked.addListener
でも動かない。 - OK: 結果的にmanifest v3では
chrome.action.onClicked.addListener
を定義するのが正しいらしい。- 使い方は色々ググったときに
browserAction
の例で出てきたものと一緒で動いた。 - manifest仕様でも
browser_action
とpage_action
がaction
に統合されているとのこと。
- 使い方は色々ググったときに
service_workerで外部jsが使えない
- 外部通信したいけど
XMLHttpRequst
めんどくさい。 - jQueryでPOSTした方が楽そうだけどjsソース複数定義できないので動作しなさそう、どうしようとなった。
- 結果的に外部js定義は使わずに実装し、通信処理は
fetch
使えばいいじゃんということにした。
Fetch の使用 - Web API | MDN - 色々やりたい場合は
{"type": "module"}
を指定してESModule
として作って諸々インポートしろってことらしい。(これは今回未実施)
自作した拡張機能用HTMLでonclick属性が動作しない
Local Storageから読み込んだ情報が想定外にObjectになった
元々Objectで取れる仕様だが作成中は勘違いしてた。(未登録でも中身が空のObjectになる)
chrome.storage.local.set({'key': 'value'}), ...
といった感じでデータ登録した場合。chrome.storage.local.get('key', (result)...
の際にresultは'value'
が直接入る(未登録ならnullなど)と思い込んでた。- 実際は
{key: 'value'}
相当のObjectが返却される。 - 指定キーが登録されていたらそのキーを含むObjectをcallbackする仕様と思われる(get時に複数キーも指定できるし)。
- ということで上記の例だと
result.key
と参照して初めて登録値が取り出せる。
JavascriptのOptional Chainがフォーマッタで崩れる
- VSCodeのBeautifyプラグインを導入してフォーマットしていた。
aaa?.bbb
といった構文をフォーマットすると場合に発生してaaa ?. bbb
と崩される。- プラグインが使っているnpmライブラリが古くて更新されていないことが原因らしい。
- 下記のページを参考にVSCodeプラグインのフォルダをカレントにして自前で
npm update
するといい感じになる。
VSCode Beautifyがnull合体演算子とオプショナルチェーンを殺しに来るとき - Qiita
プラグインの説明用に動画キャプチャ取りたいけど取得方法が不明
README.md
に利用方法の動画キャプチャ取ってGitに上げておきたいケース。
その他説明用にファイルサイズ下げたりgif化するなど動画加工などを行う場合の方法。
動画キャプチャのとり方
Win+G
でXBoxソーシャルメニューが開き、その中で動画キャプチャが可能。- キャプチャを実行すると
ドライブ:\Users\username\Videos\Captures
配下にファイルが登録される。
動画の加工方法概要
ffmpegを利用する。Windowsインストールしても良いけどDockerで実行する。
起動方法は今回下記のWebサイトを参考にした。
dockerでffmpegを構築しmkv形式をmp4形式に変換する - フリーランス 技術調査ブログ
ffmpeg起動用のDocker実行構成を作る
下記の通りdocker-compose.yaml
を作り、同階層にinput
フォルダを作って加工元ファイルを入れる。
version: '3' services: ffmpeg: container_name: ffmpeg image: jrottenberg/ffmpeg:4.1-alpine tty: true entrypoint: - "ash" volumes: - ./input:/srv/data
一応ffmpegのDockerイメージはDockerHubで最新バージョンを確認する。
Docker Hub
Docker起動して環境ログイン
alpineだとシェルはashなのでそちらを利用。
- 起動
docker-compose up -d
- ログイン
docker exec -it ffmpeg ash
キャプチャした動画を加工(圧縮)する
元々Windowsキャプチャした動画だとサイズが大きいので加工する。
- 加工元ファイルの場所へ移動
cd srv/data
- 動画加工実行
ffmpeg -i in.mp4 -vf scale=800:-1 -t 15 -r 3 out.gif
- 指定オプション説明
*1:Web公開するようなツールはセキュリティ問題が出ないように作る必要があるし、ウェブストアのツール導入時も特にマイナーなものではデータが外部流出するように定義されてないかは注意が必要。