拡張機能を自作する意味
きっかけはあるWebアプリを使っていて微妙に使いにくい、または欲しい機能がないことでした
アプリのアドオンや公開されているChrome拡張機能では求める要件を満たせるものがなく、どうにか解決できないものかと模索した結果、Chrome拡張を自作するといった方法を思いつきました
また、幸いにも求める機能は些細なものなのであまり時間をかけなくても自作できそうな見込みもありました
結果として、予想していたよりも容易に自作の拡張機能を導入できたため、ナレッジの整理も兼ねて記事にしてみました
Chrome拡張機能では多くのAPIが提供されており、詳細な使い方や各種仕様については公式ドキュメントのリンクを参考にしてください
Chrome拡張 公式ドキュメント
https://developer.chrome.com/docs/extensions
本記事では拡張機能を自身で利用する想定でまとめています
作成した拡張機能を公開する際には審査があるためご注意ください
拡張機能作成のために必要なもの
作成するためにはいくつか前提が必要です
- Webブラウザ(Chrome)
- JavaScriptの知識(DOM操作やイベントリスナーが理解できる程度)
- HTML & CSSの知識
- エディタ(VSCode推奨)
拡張機能作成の流れ
-
manifest.json
を作成する - 必要に応じてベースとなるファイルを作成する
- Chromeに拡張機能を追加する
- 追加した機能の動作を確認する
- 必要な機能を実装する
上記は拡張機能の土台を作成しChromeで動作確認後、要件に沿った実装を行う流れとなっているため、少し冗長な手順となっています
手順5の「必要な機能を実装する」の実施にあたっては、Chrome拡張の仕組みについて理解が必要になるため、記事の後半で解説します
拡張機能を作成してみよう
以下に従って、実際に拡張機能を作成していきましょう
1. manifest.json
を作成する
お好みの名前で拡張機能用のディレクトリを作成してください
サンプルでは「original-extension」ディレクトリを作成します
$ mkdir original-extension
作成したら作成したディレクトリに移動し、以下の内容でmanifest.json
を作成します
{
"manifest_version": 3,
"name": "Original Extension",
"version": "1.0",
"permissions":[],
"action": {
"default_popup": "popup.html"
}
}
name
は拡張機能の名称になるため、任意の名前に変えて問題ありません
ここでのmanifest.json
は手っ取り早く土台を作成するため、また簡単に動きが体験できるものを作成するために必要最低限の内容になっていますので、今後の本格的に実装するタイミングで適宜修正していきます
manifest.json
のフォーマットに関する公式ドキュメント
https://developer.chrome.com/docs/extensions/reference/manifest
2. 必要に応じてベースとなるファイルを作成する
まずは自作の拡張機能としてChromeにインストールするため、
続けてpopup.html
とpopup.js
を作成します
popup.html
とpopup.js
は拡張機能のアイコンクリック時のポップアップ表示用となるので、作成したい機能に不要であるならば後に削除して問題ありません。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Original Extension</title>
</head>
<body>
<button id="btn_run">run</button>
<script src="popup.js"></script>
</body>
</html>
document
.getElementById("btn_run")
.addEventListener("click", async () => {
alert("クリックされました");
});
これでベースの作成は完了です
3. Chromeに拡張機能を追加する
新しいタブでchrome://extensions/ にアクセスして右上のデベロッパーツールをオンにします
デベロッパーツールを有効化したら「パッケージ化されていない拡張機能を読み込む」から、作成したディレクトリ(サンプルではoriginal-extension)を選択します
無事読み込むことができれば以下の様に拡張機能一覧に自作の拡張機能が表示されます
4. 追加した機能の動作を確認する
以上で自作の拡張機能を実装することができました
この拡張機能をベースに実現したい機能を追加していきます
Chrome拡張機能のポイントを解説
拡張機能のベースを作成できたと思いますので、ここでChrome拡張によってできることを整理したいと思います
Chromeで拡張機能を作成したいと考えたときに、知っておくべき要素として以下の4点がありますので、それぞれ解説します
先ほどのベース作成ではToolbar actionの仕組みを利用してアラートを表示しました
Manifest
公式ドキュメントによると以下の様に説明されています
拡張機能のマニフェストは、特定のファイル名を持つ必要がある唯一のファイル(
manifest.json
)です。また、拡張機能のルート ディレクトリに配置する必要があります。このマニフェストでは、重要なメタデータの記録、リソースの定義、権限の宣言、バックグラウンドとページで実行するファイルの指定を行います。
このManifestを中心に拡張機能は構成されており、追加したい機能があればこのファイルを修正するのが基本の流れになります
また、アイコンなどの画像ファイルの定義や拡張機能が持つアクセス権限などもManifestが管理しています
ここではmanifest.json
で頻出の項目を解説します
manifest_version
Chrome拡張機能の仕様バージョンです
最新はv3となるため特に気にせずv3を設定すれば問題ありません
ただし、参考にするドキュメントによってはv2の仕様で記載されている事があるため、どのバージョンでの説明なのか注意する必要があります
content_scripts
content_scripts: []
特定のWebページに対してスクリプトやCSSを挿入したい場合に利用します(別途説明します)
action
action: {}
ツールバーに表示されている拡張機能アイコンの見た目やクリック時の動作などを定義します(別途説明します)
background
background: {}
拡張機能のService Workerを利用する場合に追加します
各種イベントに対して実行したい処理(イベントハンドラ)を定義したJavaScriptファイルを紐づけします
options_ui
options_ui: {
page: 'options/options.html',
open_in_tab: true,
},
拡張機能のオプション画面が必要な場合に追加します
オプション画面は拡張機能のアイコンを右クリックした際のメニューから「オプション」をクリック、または拡張機能の詳細画面から「拡張機能のオプション」をクリックすることで表示可能です
このオプション画面での設定値は基本的に拡張機能のstorage
を利用して保持することになります
そして保持した設定値をService Workerなどで取得して利用します
permissions
permissions: ['activeTab', 'scripting', 'storage', 'tabs']
作成する拡張機能が利用するAPIによって、拡張機能に権限を明示的に与える必要があります
そのため、permissions
をManifestに追加して拡張機能に必要な権限をリスト形式で定義します
なお、ユーザーの意思で省略できる権限についてはoptional_permissions
によって定義可能です
host_permissions
host_permissions: ['<all_urls>']
拡張機能によってWebページへの操作が発生する場合に許可されるホストのリストを定義します
web_accessible_resources
"web_accessible_resources": [
{
"resources": ["sample.png"],
"matches": ["https://*/*"]
}
]
Webページからアクセスできる拡張機能に含まれるファイルを定義します
例えば表示しているページに拡張機能で用意した画像を埋め込みたい場合は、その画像をアクセス可能なリソースとして定義します
Manifestの公式ドキュメント
https://developer.chrome.com/docs/extensions/reference/manifest
Content script
DOMへのアクセスが可能です
表示しているページの要素を取得したり、逆に変更を加えるためにはContent scriptを利用する必要があります
Content scriptではスクリプトを実行するタイミングや特定のURLにマッチする場合のみに限定する事も可能です
注意点として、Content scriptは表示しているページとは独立したコンテキストにて実行されるため、window
オブジェクトへアクセスすることはできません
利用方法
ベースとなるmanifest.json
を以下の様に修正します
{
"manifest_version": 3,
"name": "Original Extension",
"version": "1.0",
"permissions":[],
"content_scripts": [
{
"matches": [ "http://*/*", "https://*/*"],
"js": ["content-script.js"]
}
],
"action": {
"default_popup": "popup.html"
}
}
content_scripts
の項目が追加されています
その子要素であるmatches
は必須の項目であり、js
で指定したスクリプトを動作させる条件を指定します
つまりmatches
の条件に合致する場合は自動でスクリプトが動作することになります
動作タイミングが重要な場合は、run_at
の項目を追加して動作タイミングを指定する事もできます
manifest.json
にcontent_scripts
項目を追加する方法は静的宣言であり、より複雑な条件で動作させたい、動作させるスクリプトを変えたいといった場合は動的宣言(詳細は割愛)によってContent scriptを設定します
Content scriptの公式ドキュメント
https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts
Toolbar action
Chromeツールバーにある拡張機能メニュー(パズルピースのアイコン)に表示されるインストール済みの拡張機能のアイコンをアクションアイコンと呼びます
Toolbar actionではアクションアイコンをクリックしたときにポップアップを表示したり、アイコン上にバッジを表示する事が可能です
個人的にはポップアップを独自機能のメニュー、機能の実行や入力画面など拡張機能の中核となるような使い方をしています
他にもアクションアイコン(またはポップアップ内のボタン)のクリックをトリガとして、先述のContent scriptを通して、表示されているページのDOMへ間接的にアクセスすることが可能です
利用方法
Toolbar actionは前半で作成したmanifest.json
で既に利用しており、action
項目によって設定します
manifest.json
を以下の様に修正することで、アクションアイコンとして表示するアイコン画像やホバー時のツールチップ表示内容の設定が可能です
{
"manifest_version": 3,
"name": "Original Extension",
"version": "1.0",
"permissions":[],
"action": {
"default_popup": "popup.html",
"default_title": "自作の拡張機能です",
"default_icon": {
"16": "images/icon_16x16.png",
"48": "images/icon_48x48.png",
"28": "images/icon_128x128.png"
}
}
}
default_icon
に設定する画像ファイルは自身で用意し、manifest.json
と同じディレクトリ配下に格納してください
サンプルではmanifest.json
と同じディレクトリにimages
ディレクトリを用意し、その中に3種類のサイズでアイコンを格納している状況を想定しています
Toolbar actionの公式ドキュメント
https://developer.chrome.com/docs/extensions/reference/api/action
Service Worker
まずWeb APIにおけるService Workerとは別物であることに注意が必要です
ここではChrome拡張機能としてのService Workerを説明します
また、古いChrome拡張機能のバージョンであるManifest V2でのBackground Scriptとも区別する必要があります
Background Scriptとの違い
詳しく説明する場合それだけで1つの記事になるため、ここではどういった場面で利用できるかを記載します
※一部の利用例ですので他にも様々な利用方法があります
利用シーン
- 拡張機能がインストールされた場合に独自のページを表示させたい
- 時間のかかる処理をバックグラウンドで実行させたい(ただし最長で5分まで)
- 新しいページへの移動、通知をクリック、タブを閉じるといったブラウザのイベントをトリガとする処理を実行したい
Service Workerは多くの拡張機能APIを利用できるため基本的にDOM操作以外であれば何でもできる印象です
ただし、特定条件で適宜シャットダウンされるため、データは必要に応じてchrome.storage APIなどに保持しておきましょう
利用方法
manifest.json
を以下の様に修正します
{
"manifest_version": 3,
"name": "Original Extension",
"version": "1.0",
"permissions":[],
"background": {
"service_worker": "service-worker.js"
},
"action": {
"default_popup": "popup.html"
}
}
background
項目が追加されています
service-worker.js
にはイベントハンドラの登録処理などを記述します
Service Workerの公式ドキュメント
https://developer.chrome.com/docs/extensions/develop/concepts/service-workers
その他できること
Chrome拡張機能では他にも様々なできることがあります
いくつかピックアップして紹介します
テーマの変更
manifest.json
にtheme
項目を追加するとブラウザのテーマを変更する拡張機能を作成できます
ブックマーク マネージャー、履歴、新しいページのUI変更
例えばChromeで新しいタブを開くとgoogleの検索フォームが表示されますが、この画面を任意のコンテンツに変更することができます
この機能によって自分好みの使いやすいUIを実現できます
サイドバー表示
Side Panel APIを利用するとメインのページとは別に拡張機能で用意されたコンテンツをサイドバーとして表示できます
このサイドバーはタブを切り替えても同じ内容が表示されるため、タブを跨いで共通の内容を利用可能です
タブの管理
chrome.tabs APIを利用するとブラウザで開かれているタブの一覧やアクティブなタブの取得、タブの作成や変更といった操作が可能になります
ネットワークリクエストの傍受、ブロック、変更
chrome.declarativeNetRequest APIを利用するとネットワークリクエストを監視し、定義したルールに沿ってリダイレクト、ブロック、クエリパラメータの追加など様々な制御を加えることが可能になります
次回の内容について
今回の記事だけでまとめきれなかったので2本立てとなりそうです
次回は以下のトピックを扱う予定です
- メッセージ通信の仕組み
- デバッグ方法
- 拡張機能実装時の注意点
- 拡張機能テンプレートの利用
- React & TypeScriptを活用した拡張機能の実装
- Tailwind CSSでお手軽デザイン
- Jestでのテスト自動化
少し時間がかかるかもしれませんが楽しみにしていただければ幸いです