10
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

拡張機能を自作する意味

きっかけはあるWebアプリを使っていて微妙に使いにくい、または欲しい機能がないことでした
アプリのアドオンや公開されているChrome拡張機能では求める要件を満たせるものがなく、どうにか解決できないものかと模索した結果、Chrome拡張を自作するといった方法を思いつきました
また、幸いにも求める機能は些細なものなのであまり時間をかけなくても自作できそうな見込みもありました
結果として、予想していたよりも容易に自作の拡張機能を導入できたため、ナレッジの整理も兼ねて記事にしてみました
Chrome拡張機能では多くのAPIが提供されており、詳細な使い方や各種仕様については公式ドキュメントのリンクを参考にしてください

Chrome拡張 公式ドキュメント
https://developer.chrome.com/docs/extensions

本記事では拡張機能を自身で利用する想定でまとめています
作成した拡張機能を公開する際には審査があるためご注意ください

拡張機能作成のために必要なもの

作成するためにはいくつか前提が必要です

  • Webブラウザ(Chrome)
  • JavaScriptの知識(DOM操作やイベントリスナーが理解できる程度)
  • HTML & CSSの知識
  • エディタ(VSCode推奨)

拡張機能作成の流れ

  1. manifest.jsonを作成する
  2. 必要に応じてベースとなるファイルを作成する
  3. Chromeに拡張機能を追加する
  4. 追加した機能の動作を確認する
  5. 必要な機能を実装する

上記は拡張機能の土台を作成しChromeで動作確認後、要件に沿った実装を行う流れとなっているため、少し冗長な手順となっています
手順5の「必要な機能を実装する」の実施にあたっては、Chrome拡張の仕組みについて理解が必要になるため、記事の後半で解説します

拡張機能を作成してみよう

以下に従って、実際に拡張機能を作成していきましょう

1. manifest.jsonを作成する

お好みの名前で拡張機能用のディレクトリを作成してください
サンプルでは「original-extension」ディレクトリを作成します

$ mkdir original-extension

作成したら作成したディレクトリに移動し、以下の内容でmanifest.jsonを作成します

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.htmlpopup.jsを作成します

popup.htmlpopup.jsは拡張機能のアイコンクリック時のポップアップ表示用となるので、作成したい機能に不要であるならば後に削除して問題ありません。

popup.html
<!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>
popup.js
document
  .getElementById("btn_run")
  .addEventListener("click", async () => {
    alert("クリックされました");
  });

これでベースの作成は完了です

3. Chromeに拡張機能を追加する

新しいタブでchrome://extensions/ にアクセスして右上のデベロッパーツールをオンにします
デベロッパーツールを有効化したら「パッケージ化されていない拡張機能を読み込む」から、作成したディレクトリ(サンプルではoriginal-extension)を選択します

image.png

無事読み込むことができれば以下の様に拡張機能一覧に自作の拡張機能が表示されます

image.png

4. 追加した機能の動作を確認する

  1. 拡張機能アイコンをクリックして表示される一覧に自作の拡張機能が表示されているはずなのでピン留めアイコンをクリックしておきます
    image.png

  2. 拡張機能アイコンの隣に表示されたアイコンをクリックします(画像では「O」と表示)
    image.png

  3. popup.htmlの内容が表示されるので「run」ボタンをクリックします
    image.png

  4. アラートが表示されたら確認完了です
    image.png

以上で自作の拡張機能を実装することができました
この拡張機能をベースに実現したい機能を追加していきます

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.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.jsoncontent_scripts項目を追加する方法は静的宣言であり、より複雑な条件で動作させたい、動作させるスクリプトを変えたいといった場合は動的宣言(詳細は割愛)によってContent scriptを設定します

Content scriptの公式ドキュメント
https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts

Toolbar action

Chromeツールバーにある拡張機能メニュー(パズルピースのアイコン)に表示されるインストール済みの拡張機能のアイコンをアクションアイコンと呼びます

image.png

Toolbar actionではアクションアイコンをクリックしたときにポップアップを表示したり、アイコン上にバッジを表示する事が可能です
個人的にはポップアップを独自機能のメニュー、機能の実行や入力画面など拡張機能の中核となるような使い方をしています
他にもアクションアイコン(またはポップアップ内のボタン)のクリックをトリガとして、先述のContent scriptを通して、表示されているページのDOMへ間接的にアクセスすることが可能です

利用方法

Toolbar actionは前半で作成したmanifest.jsonで既に利用しており、action項目によって設定します
manifest.jsonを以下の様に修正することで、アクションアイコンとして表示するアイコン画像やホバー時のツールチップ表示内容の設定が可能です

manijest.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を以下の様に修正します

manijest.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.jsontheme項目を追加するとブラウザのテーマを変更する拡張機能を作成できます

ブックマーク マネージャー、履歴、新しいページのUI変更

例えばChromeで新しいタブを開くとgoogleの検索フォームが表示されますが、この画面を任意のコンテンツに変更することができます
この機能によって自分好みの使いやすいUIを実現できます

サイドバー表示

Side Panel APIを利用するとメインのページとは別に拡張機能で用意されたコンテンツをサイドバーとして表示できます
このサイドバーはタブを切り替えても同じ内容が表示されるため、タブを跨いで共通の内容を利用可能です

タブの管理

chrome.tabs APIを利用するとブラウザで開かれているタブの一覧やアクティブなタブの取得、タブの作成や変更といった操作が可能になります

ネットワークリクエストの傍受、ブロック、変更

chrome.declarativeNetRequest APIを利用するとネットワークリクエストを監視し、定義したルールに沿ってリダイレクト、ブロック、クエリパラメータの追加など様々な制御を加えることが可能になります

次回の内容について

今回の記事だけでまとめきれなかったので2本立てとなりそうです
次回は以下のトピックを扱う予定です

  • メッセージ通信の仕組み
  • デバッグ方法
  • 拡張機能実装時の注意点
  • 拡張機能テンプレートの利用
  • React & TypeScriptを活用した拡張機能の実装
  • Tailwind CSSでお手軽デザイン
  • Jestでのテスト自動化

少し時間がかかるかもしれませんが楽しみにしていただければ幸いです

10
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?