Chrome拡張機能(Manifest V3)の開発で知ったこと
皆さん、Chrome 拡張機能をご存知ですか? Chrome 拡張機能は、Chrome ブラウザをカスタマイズするための機能です。
私は、Chrome 拡張機能を過去(数年前)に 2 つ作っていて、その当時は、Chrome 拡張機能の仕様である Manifest V2 に従っていました。 そして、今再び、Chrome 拡張機能で作りたいものができたので、久々に作ろうと決意しました。 作ろうと思ったものの、どうやら今の Chrome 拡張機能の仕様は Manifest V3 を推奨しているようです。 そこで、今回、開発した際に知ったことをまとめようと思います。
ちなみに、実際に作ったものは次のものです。
- https://github.com/silverbirder/chrome-extensions-tiktok-scraping-downloader
- 上にある図が、この Chrome 拡張機能の設計図になります
※ Chrome 拡張機能の概要について詳しく知りたい方は、What are extensions? - Chrome Developersをご覧ください。
Chrome Extensions Components
Chrome 拡張機能は、主に次の 4 つのコンポーネントが存在します。
- Background Scripts
- サービスワーカー上で動作し、ブラウザ上のイベント駆動(ページ遷移やブックマーク差所など)で反応します。
- manifestの
background
フィールドで設定します。
- Content Scripts
- Web ページのコンテキスト上で動作し、DOM へアクセスできます。
- manifestの
content_scripts
フィールドで設定します。
- UI Elements
- URL バーの右側にあるボタンを押した(Action)際に表示される UI です。
- ブラウザ体験を損なわさない最低限の機能だけの提供を推奨されています。
- manifestの
action
フィールドで設定します。
- Options Page
- Chrome 拡張機能アイコンを右クリックして、オプションを選択すると表示される UI です。
- Chrome 拡張機能をカスタマイズしたい設定ページに使います。
- manifestの
options_page
フィールドで設定します。
私なりに、これらのコンポーネントの使い分けを考えると、次になります。
- DOM へアクセスする必要がある
- Content Scripts を使う
- ページに依存しない処理がある
- Background Scripts を使う
- 環境変数の設定が必要
- Option Page
UI Elements は、基本的に必要ないのかなと思いました。
Debug
デバッグって、どうやるんでしょうか。
こちらにやり方が書いてありました。 私なりに解釈した結果、次の 2 つで使い分けるのかなと思います。
- ① そもそも、Chrome 拡張機能がロードできない場合
manifest.json ファイルに記述で誤りがあるなどで、Chrome 拡張機能がロードできない場面があります。 そういうときは、次の手順を実行します。
chrome://extensions
へアクセス- 次の図にあるような ERROR ボタンをクリック
恐らく、何かしらエラーメッセージが出力されていると思います。 それを解決しましょう。
- ② ① 以外の場合
Chrome 拡張機能はロードできるが、期待通りに動作しない場面があると思います。 そういうときは、DevTools を開きましょう。
- Background Scripts の場合
chrome://extensions
へアクセスし、inspect views
の右にあるリンクをクリック。(上図)- DevTools が開きます。
- Content Scripts, UI Elements, Options Page の場合
- UI 上で右クリックして
Inspect
をクリック- DevTools が開きます。
- UI 上で右クリックして
DevTools には、console タブがあるはずです。そこのログメッセージを確認しましょう。
Message Passing
各コンポーネント間で、通信するのは、どうしたら良いのでしょうか。 例えば、Content Scripts から Background Scripts へデータを渡したいときなどです。 次の資料が、参考になります。
資料を読むと、次のようなパターンの通信ができるようです。
- 各コンポーネント間の通信
- Background Scripts ⇔ Content Scripts など
- Chrome 拡張機能間の通信
- A Chrome 拡張機能 ⇔ B Chrome 拡張機能
- Chrome 拡張機能の ID を使って通信します
- Web ページからの通信(Sending messages from web pages)
- Web ページ ⇔ Chrome 拡張機能のコンポーネント
通信の具体的なコードは、chrome.runtime.sendMessage
メソッドを使います。
Background Scripts から Content Scripts へ通信する場合、どの Chrome タブに送信するかchrome.tabs.query
で事前に id を見つけておく必要があります。
また、後で紹介しますが、Web Accessible Resources
でアクセス可能な Javascript を Web ページへ Inject(document.querySelector('body').append()
)した場合、その Javascript と Content Scripts の通信は、window.postMessage
とwindow.addEventListener
を使いましょう。
chrome.runtime
が使えないので。
Web Accessible Resources
Content Scripts から Web ページの DOM へアクセスできますが、window オブジェクトにある変数へアクセスすることができません。
window オブジェクトへアクセスするには、Web Accessible Resources を使う方法があります。
具体的にコードで説明しましょう。
manifest.json で必要なフィールドの例は、次のとおりです。
{
"manifest_version": 3,
"content_scripts": [
{
"js": ["content-script.js"],
"matches": ["https://*/*"]
}
],
"web_accessible_resources": [
{
"resources": ["web_accessible_resources.js"],
"matches": ["https://*/*"]
}
]
}
Content Scripts と Web Accessible Resources の Javascript は次のとおりです。
// content-script.js
const injectScript = (filePath, tag) => {
var node = document.getElementsByTagName(tag)[0];
var script = document.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("src", filePath);
node.appendChild(script);
};
injectScript(chrome.runtime.getURL("web_accessible_resources.js"), "body");
// web_accessible_resources.js
console.log(window["hoge"]);
// Content Scriptsへ通信する場合は、window.postMessageを使います。
このように、web_accessible_resources.js を Web ページの body タグへ append します。 その web_accessible_resources.js では、window オブジェクトにアクセスすることができます。
chrome.webRequest API
Chrome ブラウザでネットワークトラフィックを監視する Chrome 拡張機能の API があります。
それが、chrome.webRequest
です。
これがあれば、Web ページでどういうリクエストが発生しているか分かるようになります。
manifest.json のフィールドで、host_permissions
の設定が必要です。
サンプルで、Background Scripts のコードを紹介します。 まず、manifest.json の必要なフィールドを書きます。
{
"manifest_version": 3,
"host_permissions": ["https://*/*"],
"background": {
"service_worker": "background.js"
}
}
次に、Web ページからリクエストが完了(onCompleted)したイベントを監視するコードを書きます。
// background.js
chrome.webRequest.onCompleted.addListener(
async (details) => {
console.log(`request url is ${details.url}`);
},
{
urls: ["https://*/*"],
},
["responseHeaders"] // responseHeadersをdetailsオブジェクトに含めることができます。
);
この details にはリクエストの URL が含まれています。さらに詳しく知りたい人は、こちらをご確認ください。
最後に
Chrome 拡張機能、久々に開発してみると、進化しすぎていてキャッチアップに苦労しました。 私と同じような方の助けになれば、幸いです。
Tags
2023-07-17
最近、ビアードパパの焼きチーズケーキシューにハマっている silverbirder です。文章作成が苦手な私は、AI が文章を代筆する「AI Ghostwriter」という Chrome の拡張機能を開発しました。今回は、この便利なツールの紹介をします。...