拡張機能開発に必要な概念〜3つの構成要素〜
拡張機能作成のややこしさは拡張機能に特有の用語が多用されることです。用語が指す概念は初めはとっつきにくいものの、一度慣れてしまえば意識することなく拡張機能開発に取り組むことができます。
本ページでは「カスタムUI」「コンテンツスクリプト」「バックグラウンドスクリプト」を紹介し、本書ではそれらをまとめて「3つの構成要素」と呼ぶことにします。大まかに説明すると、「カスタムUI」は拡張機能で扱う情報を表示するUI部分です。「コンテンツスリプト」は対象サイトのDOMにアクセスすることができるCSSファイルとJavaScriptファイルのことです。「バックグラウンドスクリプト」はバックグラウンドで実行されるJavaScriptファイルのことです。この3つの構成要素の役割と関係性を意識すると、拡張機能開発の全体像を把握しながら学習することができます。「3つの構成要素」と説明する元ネタはこちらの記事から参考にさせてもらいました。https://qiita.com/sakaimo/items/416f36db1aa982d8d00c
カスタムUI
カスユーザーが拡張機能を操作・設定したり、情報を確認することができるUIです。拡張機能では拡張機能の情報を表示させる画面や操作のトリガーとなるボタンを設置できる箇所が複数用意されているため、本書ではこれらをまとめて「カスタムUI」と呼ぶことにします。次に紹介するように、表示したい場所やシーンによってカスタムUIを使い分けることができます。
アイコンを除く、全てのカスタムUIはHTML、CSS、JavaScriptでUIを構築することになります。本書では解説しませんが、React や Vue などのUIライブラリ、フレームワークを使ってUIを構築することもできます。
カスタムUIは状態を持たないので、カスタムUIを閉じてしまうと保存していない情報は消えてしまいます。フォームを設置してユーザーが情報を入力、変更する場合はバックグラウンドスクリプトを経由して情報を保存する必要があります。
カスタムUIで使うことができる Chrome API は限られています。
アイコン
ブラウザのツールバーに常に表示されるものです。好きな画像をアイコンに設定することができます。アイコンをクリックすると次に説明する「ポップアップ」を表示させることができたり、クリックしたときに特定の処理を引き起こすためのイベントトリガーとして扱うことができます。
ポップアップ
ポップアップは拡張機能アイコンをクリック、またはchrome.action.openPopup()
の呼び出しによって表示されるカスタムUIです。拡張機能アイコンはどのタブを開いていても常に表示されているので、全てのサイトに対応した拡張機能を作るときに便利です。
カスタムUIは情報を持たないことは先ほど説明しましたが、ポップアップも情報を持たないので保存していない情報は初期化されてしまします。カスタムUIの中でポップアップはなにか特別な感じがするのですが、少し固有の Chrome API があったり表示されている位置は目立つものの、提供されている機能は他のカスタムUIほとんど同じです。なので情報を保持したい場合はデータを保存する必要があります。ポップアップを使用する場合はmanifest.json
のdefault_popup
で表示するHTMLを指定する必要があります。
オプションページ
オプションページはユーザーが拡張機能の設定の変更するための特別なページです。個別のタブで表示され、1つのWebページのように扱うことができます。
オプションページの作成は任意です。なのでオプションページ以外でも拡張機能の設定を変更することはできます。作成する拡張機能によってはオプションページ以外で設定を入力するのが便利である場合や、そもそも設定する項目がない場合もあるでしょう。オプションページを利用する場合、拡張機能アイコンを右クリックしたとき「オプション」というメニューが自動で作成されます。「オプション」をクリックするとオプションページが開きます。拡張機能を使い慣れているユーザーにとって拡張機能の設定画面を開くときに統一されている方が便利な場合もあるでしょう。オプションページを使用する場合はmanifest.json
のoptions_page
に表示するHTMLを指定する必要があります。
カスタムページ
拡張機能では自前で用意したHTMLページを開くことができます。正式名称はないのですが本書ではこれをカスタムページと呼ぶことにします。拡張機能ではカスタムUIとして、さまざまなUIが提供されているのでちょっとした情報を表示する場合は他のカスタムUIやコンテンツスクリプトを利用するだけで十分です。ただし作りたい拡=張機能によっては個別のページとして大きな画面で表示したいときに役立つUIです。
下の画像はDeepLの拡張機能ををインストールした直後に表示されるページです。一見別のWebページに飛ばされたように見えますが、URLのスキーム部分を見るとchrome-extension://
となっており、通常のWebページとは異なる画面だということがわかります。
パネル
パネルは DevTools 内に表示される個別のツールウィンドウです。デフォルトでは「要素」「コンソール」「ネットワーク」などのWebページのデバッグをするのに便利なツールがここに収納されています。パネルには他のカスタムUIと違ってネットワークリクエストにアクセスできたり、対象ページ内で任意のJavaScriptを実行できる Chrome API が提供されています。他の構成要素ではアクセスできない情報を取得されている権限が与えられている一方で、セキュリティのため DevTools はユーザー自身が手動で開かなければなりません。他のカスタムUIのようにコード上で起動する方法はありません。パネルを作成する場合は、manifest.json
のoptions_page
に表示するHTMLを指定する必要があります。
コンテンツスクリプト
コンテンツスクリプトは対象サイトに挿入されるCSSとJavaScriptのファイルです。対象サイトのDOMにアクセスすることができ、Webページの情報を読み取り、変更を加えたり、3つの構成要素に情報を渡すことができます。
対象サイトに挿入されるとはいえ、対象サイトや他の拡張機能のコンテンツスクリプトとは分離した環境でコンテンツスクリプトは実行されます。なので変数名が衝突が発生することはないですし、お互いの関数を他方から実行することはできません。コンテンツスクリプトから対象サイトのDOMにアクセスすることはできますが、対象サイトからコンテンツスクリプトの変数や関数にはアクセスすることができません。
このように対象サイトへ自由にアクセスできる一方で、提供されている Chrome API は限られています。コンテンツスクリプトでは具体的に次のようなことができます。
- 自作のDOMを挿入する
- 対象サイトの見た目を書き換える
- 対象サイトの要素を編集、削除する
- Webページの操作を自動化する
- Webページの情報を加工して表示する
バックグラウンドスクリプト
バックグラウンドスクリプトとはバックグラウンドで実行されるJavaScriptのファイルです。バックグラウンドスクリプト主な役割は拡張機能のイベントハンドラです。カスタムUIやコンテンツスクリプトでイベントが発生したタイミングにメッセージを送り、バックグラウンドがメッセージを受信したタイミングで必要な必要な情報を取得・加工し、メッセージ送信元へ返す処理をメインに行います。この一連の流れをメッセージ受け渡しと呼び、次に解説します。
バックグラウンドスクリプトは利用できる Chrome API が豊富である一方、対象サイトのDOMへのアクセスはできません。カスタムUIとコンテンツスクリプトが画面上に表示される一方で、バックグラウンドスクリプトはその名の通り画面には表示されない裏方の役割をになっています。バックグラウンドスクリプトだけで利用できる Chrome APIを使って次のようなことができます。
-
storage
を使ってデータを保存したり読み込む -
tabs
を使って他のタブで開いているサイトの情報を読み取る -
downloads
を使ってダウンロードの状況を管理する -
webRequest
を使ってネットワークリクエストを書き換える
まとめ
3つの構成要素の特徴をまとめると次のような表になります。
カスタムUI | コンテンツスクリプト | バックグラウンドスクリプト | |
---|---|---|---|
対象サイトDOMへのアクセス | できない | できる | できない |
使える Chrome API の種類 | 少ない | 少ない | 多い |
メッセージ受け渡し
3つの構成要素は単体で見ると機能は豊富なのですが単体では使える機能が非常に限られています。例えばコンテンツスクリプトでは指定したサイトのDOMにアクセスできるのでページ上のデータの読み書きや新しい画面の追加が行えます。しかし提供されている Chrome API が貧弱なためデータの保存や他のタブとのやり取りができません。バックグラウンドでは提供されている Chrome API が豊富なためデータの保存を行えたり、ダウンロードの実行が行えますが、指定サイトのDOMにアクセスすることができません。
そこで構成要素同士が通信を行うことで、単体ではアクセスできないデータや実行できない処理を活用することができ、充実した機能を持つ拡張機能を作ることができます。このように構成要素同士がデータを送受信する仕組みをメッセージ受け渡しと言います。メッセージ受け渡しではJavaScriptのオブジェクト型のデータを渡すことができます。例えばコンテンツスクリプトで受信した対象サイトのDOMをバックグラウンドへ送信し、storage
を使ってストレージに保存するといったことができるようになります。また、必ずしもデータを送る必要はありません。例えばポップアップでボタンをクリックしたときにメッセージを送り、バックグラウンドでstorage
を使い保存したデータを取り出し、ポップアップで表示することもできます。このようにメッセージ受け渡しを動作を行うトリガーとして利用することもできます。
メッセージ受け渡しは必ずしもバックグラウンドスクリプトをを経由する必要はありません。カスタムUIとコンテンツスクリプト同士でもメッセージ受け渡しはできます。またメッセージを送受信するコードさえ書けば複数の経路を取っても構いませんし、行ったり来たりしても構いません。。よってメッセージ受け渡しのイメージは次の図のようなイメージになります。
拡張機能を開発するとき、3つの構成要素のうちの1つだけを使うというのは機能が制限されるため少ないです。便利な拡張機能を作ろうとするとメッセージ受け渡しは必要になってきます。
Discussion