{{AddonSidebar}}
初めての WebExtension を一通り読んでいる場合、既に Web Extension の書き方を知っていることと思います。この記事では、API の使い方をより詳しく説明するため、前回よりも少し複雑なアドオンを書いてみます。
このアドオンでは Firefox のツールバーにボタンを新しく追加します。このボタンをユーザがクリックすると、動物を選択できるポップアップが表示されます。ユーザが動物を選択すると、Web ページのコンテンツが選択した動物の画像に置き換わります。
これらの機能を以下のように実装していきます。
- browser action(Firefox のツールバーに表示させるボタン)を定義
このボタン用に次のものを用意します。- "beasts-32.png" というアイコン
- ボタン押下時に開くポップアップ(HTML / CSS / JavaScript で記述)
- アドオンのアイコンを定義
このアイコン(ファイル名: "beasts-48.png")はアドオンマネージャに表示されます。 - Web ページに読み込ませる content script "beastify.js" を作成
このスクリプトによって Web ページが実際に変更されます。 - Web ページを置き換える動物の画像をパッケージ化
画像を "web-accessible なリソース" とし、Web ページから参照できるようにします。
このアドオンは次のような全体構成になっています。
このアドオンはシンプルですが、WebExtensions API の基本的なコンセプトを多く含んでいます。
- ツールバーにボタンを追加する
- HTML / CSS / JavaScript を用いてポップアップのパネルを定義する
- Web ページに content script を差し込む
- 拡張機能の中において content script と他のスクリプトとを通信させる
- Web ページで用いるリソースをアドオンにパッケージ化する
WebExtension を書く
新しいディレクトリを作成し、そのディレクトリに移動します。
mkdir beastify cd beastify
manifest.json
それでは、"beastify" ディレクトリ配下に新しいファイル "manifest.json" を作成します。以下の内容を書き込んで保存してください。
{
"manifest_version": 2,
"name": "Beastify",
"version": "1.0",
"description": "Adds a browser action icon to the toolbar. Click the button to choose a beast. The active tab's body content is then replaced with a picture of the chosen beast. See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Examples#beastify",
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/beastify",
"icons": {
"48": "icons/beasts-48.png"
},
"applications": {
"gecko": {
"id": "[email protected]",
"strict_min_version": "45.0"
}
},
"permissions": [
"activeTab"
],
"browser_action": {
"default_icon": "icons/beasts-32.png",
"default_title": "Beastify",
"default_popup": "popup/choose_beast.html"
},
"web_accessible_resources": [
"beasts/frog.jpg",
"beasts/turtle.jpg",
"beasts/snake.jpg"
]
}
- 最初の 3 つのキー
manifest_version
、name
、version
は必須であり、アドオンの基本的なメタデータを指定します。 description
は省略可能ですが、設定しておくことをお勧めします。この値はアドオンマネージャに表示されます。icons
は省略可能ですが、 設定しておくことをお勧めします。この値はアドオンのアイコンを指定するものであり、アイコンはアドオンマネージャに表示されます。applications
は(Chrome 拡張機能と異なり)Firefox における必須項目であり、アドオンの ID を指定します。他にも、アドオンがサポートする Firefox のバージョンについて、最小値・最大値を指定することが可能です。permissions
はアドオンに必要なパーミッションのリストです。ここではactiveTab
パーミッション を要請しています。browser_action
はツールバーのボタンを指定するものです。ここでは 3 つの情報を指定しています。default_icon
ではボタンのアイコンを指定します(必須項目)。default_title
ではツールチップの文字列を指定します(省略可)。default_popup
ではユーザがボタンをクリックした際に表示されるポップアップを指定します。今回はポップアップを表示させたいので、アドオンに含める HTML ファイルをdefualt_popup
キーで指定しています。
web_accessible_resources
は Web ページからアクセスしたいファイルのリストです。このアドオンでは、拡張機能に同梱した画像で Web ページを置き換えるため、画像を Web ページからアクセス可能にする必要があります。
パスはすべて manifest.json 自身からの相対パスで指定することに注意してください。
アイコン
アドオンにはアイコンを用意すると良いでしょう。このアイコンは、アドオンマネージャでアドオンのリスト横に表示されます(アドオンマネージャは "about:addons" の URL から確認できます)。 今回の manifest.json では "icons/beasts-48.png" を用意していると宣言しています。
まずは "beastify" ディレクトリの下に "icons" ディレクトリを作成します。次に、アイコンを "border-48.png" という名前で "icons" ディレクトリ内に保存します。必要であれば サンプルで使用しているアイコン を利用しても構いません(このアイコンは Aha-Soft’s Free Retina iconset から引用したものであり、該当する ライセンス の下で使用しています)。
ここでアイコンを自分で用意する場合は 48x48 ピクセルのサイズにする必要があります。高解像度のディスプレイには 96x96 ピクセルのアイコンを表示させたい場合は、manifest.json の icons
オブジェクトに 96
というプロパティで設定してください。
"icons": {
"48": "icons/beasts-48.png",
"96": "icons/beasts-96.png"
}
ツールバーのボタン
ツールバーのボタンにもアイコンが必要です。 今回の manifest.json では "button/beasts.png" を用意していると宣言しています。
まずは "beastify" ディレクトリの下に "button" ディレクトリを作成します。次に、アイコンを "beasts.png" という名前で "button" ディレクトリ内に保存します。必要であれば サンプルで使用しているアイコン を利用しても構いません(このアイコンは IconBeast Lite のアイコン集 から引用したものであり、該当する ライセンス の下で使用しています)。
ポップアップを使わない場合、ユーザがボタンをクリックした際にはクリックイベントがアドオンに向けて送出されます。ポップアップを使う場合にクリックイベントは送出されず、代わりにポップアップが開きます。今回はポップアップが必要なので、次の項で作成しましょう。
ポップアップ
今回のポップアップでは、ユーザが 3 つの動物から 1 つ選択できる機能を持つこととします。
アドオンのルート配下に "popup" というディレクトリを新しく作成します。ここにはポップアップ用のコードを保管します。ポップアップは次の 3 ファイルから構成されます。
choose_beast.html
パネルのコンテンツを定義するchoose_beast.css
コンテンツのスタイルを指定するchoose_beast.js
アクティブなタブで content script を実行し、ユーザの選択を処理する
choose_beast.html
HTML ファイルは次のようになります。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <link rel="stylesheet" href="choose_beast.css"/> </head> <body> <div class="beast">Frog</div> <div class="beast">Turtle</div> <div class="beast">Snake</div> <script src="choose_beast.js"></script> </body> </html>
単にここでは動物ごとに要素を与えています。通常の Web ページと同じように CSS と JS ファイルを読み込んでいることに注意してください。
choose_beast.css
この CSS ではポップアップのサイズを固定、3 つの選択肢で空白を埋めることを保証し、基本的なスタイリングを与えます。
html, body {
width: 100px;
}
.beast {
margin: 3% auto;
padding: 4px;
text-align: center;
font-size: 1.5em;
background-color: #E5F2F2;
cursor: pointer;
}
.beast:hover {
background-color: #CFF2F2;
}
choose_beast.js
ポップアップ用の JavaScript ではクリックイベントをリッスンします。3 つの動物のどれかがクリックされた場合、アクティブなタブに content script を差し込みます。content script が読み込まれると、動物の選択のメッセージを送ります:
/*
動物の名前を受け取り、対応する画像の URL を返す
*/
function beastNameToURL(beastName) {
switch (beastName) {
case "Frog":
return chrome.extension.getURL("beasts/frog.jpg");
case "Snake":
return chrome.extension.getURL("beasts/snake.jpg");
case "Turtle":
return chrome.extension.getURL("beasts/turtle.jpg");
}
}
/*
ポップアップのクリックイベントをリッスンする。
動物以外がクリックされた場合は最初で return する。
そうでない場合、クリックされたノードの textContent から動物の名前を取得する。
アクティブなタブに content script "beastify.js" を差し込む。
続いて、アクティブなタブへの参照を取得し、"beastify.js" にメッセージを送信する。
このメッセージには、選択された動物に対応する画像の URL を含んでいる。
*/
document.addEventListener("click", function(e) {
if (!e.target.classList.contains("beast")) {
return;
}
var chosenBeast = e.target.textContent;
var chosenBeastURL = beastNameToURL(chosenBeast);
chrome.tabs.executeScript(null, {
file: "/content_scripts/beastify.js"
});
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {beastURL: chosenBeastURL});
});
});
ここでは 3 つの WebExtension API メソッドを使用しています。
chrome.tabs.executeScript
は "content_scripts/beastify.js" にあるコンテントスクリプトをアクティブなタブに注入しますchrome.tabs.query
はアクティブなタブを取得しますchrome.tabs.sendMessage
はアクティブなタブ内で実行されるコンテントスクリプトにメッセージを送ります。メッセージはbeast
プロパティにある選択した動物が入っています。
コンテントスクリプト
拡張機能のルートフォルダの下に、"content_scripts" という名のディレクトリを新規作成し、その中に "beastify.js" という名のファイルを作成し、下記のコンテンツを記述します:
// Assign beastify() as a listener for messages from the extension. chrome.runtime.onMessage.addListener(beastify); function beastify(request, sender, sendResponse) { removeEverything(); insertBeast(beastNameToURL(request.beast)); chrome.runtime.onMessage.removeListener(beastify); } function removeEverything() { while (document.body.firstChild) { document.body.firstChild.remove(); } } function insertBeast(beastURL) { var beastImage = document.createElement("img"); beastImage.setAttribute("src", beastURL); beastImage.setAttribute("style", "width: 100vw"); beastImage.setAttribute("style", "height: 100vh"); document.body.appendChild(beastImage); } function beastNameToURL(beastName) { switch (beastName) { case "Frog": return chrome.extension.getURL("beasts/frog.jpg"); case "Snake": return chrome.extension.getURL("beasts/snake.jpg"); case "Turtle": return chrome.extension.getURL("beasts/turtle.jpg"); } }
コンテントスクリプトは拡張機能からの(特に、上記 "choose_beast.js" からの)メッセージに対するリスナーを追加します リスナー内で、これは次のことを行います:
document.body 内のすべての要素を削除します。
- 動物名を、画像を指定する URL に変換します。
- URLを指定する
<img>
要素を作り、DOM に挿入する - メッセージリスナを削除する
動物
最後に、動物の画像を入れておく必要があります。
"beasts" という名のディレクトリを作成し、その中に3つの画像を、適切な名前をつけて追加します。GitHub リポジトリから画像を取得できます、あるいはここからでも:
パッケージ化とインストール
正しいファイルが正しい場所にあるかどうか、再チェックします:
beastify/ beasts/ frog.jpg snake.jpg turtle.jpg button/ beasts.png content_scripts/ beastify.js popup/ choose_beast.css choose_beast.html choose_beast.js manifest.json
Firefox 拡張機能は XPI ファイルとしてパッケージ化されます、これは単に"xpi" の拡張子つきのZIPファイルです。
つまづきポイントとしては、ZIP ファイルは拡張機能の中のファイルを、一つのZIPにしたものである必要があり、格納ディレクトリをZIP化したものではありません。なので動物化のファイルから、一つのXPIを作るには、 コマンドシェルで"beastify" ディレクトリに移動して、次のようにタイプします:
# in beastify/ zip -r ../beastify.xpi *
XPI をインストールするには、単に Firefox で開きます:
- ファイルメニューから開くを選ぶ、または Ctrl/Cmd+O を押す
- 選択ダイアログから "beastify.xpi" を選択する
署名されていない拡張機能をインストールする旨の警告が出るでしょう、警告を受諾します。
Firefoxツールバーにアイコンが出現するのが見えるでしょう。webページを開いて、アイコンをクリックし、動物を選択すると、webページの画像が変化するのが見えます。