Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Revision 1035104 of 2 つめの WebExtension

  • リビジョンの URL スラグ: Mozilla/Add-ons/WebExtensions/Walkthrough
  • リビジョンのタイトル: Walkthrough
  • リビジョンの ID: 1035104
  • 作成日:
  • 作成者: hashedhyphen
  • 現行リビジョン? いいえ
  • コメント

このリビジョンの内容

{{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 ページで用いるリソースをアドオンにパッケージ化する

ソースコード一式は GitHub で参照できます

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_versionnameversion は必須であり、アドオンの基本的なメタデータを指定します。
  • 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ページの画像が変化するのが見えます。

 

 

 

このリビジョンのソースコード

<p>{{AddonSidebar}}</p>

<p><a href="https://developer.mozilla.org/ja/Add-ons/WebExtensions/Your_first_WebExtension">初めての WebExtension</a> を一通り読んでいる場合、既に Web Extension の書き方を知っていることと思います。この記事では、API の使い方をより詳しく説明するため、前回よりも少し複雑なアドオンを書いてみます。</p>

<p>このアドオンでは Firefox のツールバーにボタンを新しく追加します。このボタンをユーザがクリックすると、動物を選択できるポップアップが表示されます。ユーザが動物を選択すると、Web ページのコンテンツが選択した動物の画像に置き換わります。</p>

<p>これらの機能を以下のように実装していきます。</p>

<ul>
 <li><strong>browser action(Firefox のツールバーに表示させるボタン)を定義</strong><br />
  このボタン用に次のものを用意します。
  <ul>
   <li>"beasts-32.png" というアイコン</li>
   <li>ボタン押下時に開くポップアップ(HTML / CSS / JavaScript で記述)</li>
  </ul>
 </li>
 <li><strong>アドオンのアイコンを定義</strong><br />
  このアイコン(ファイル名: "beasts-48.png")はアドオンマネージャに表示されます。</li>
 <li><strong>Web ページに読み込ませる content script "beastify.js" を作成</strong><br />
  このスクリプトによって Web ページが実際に変更されます。</li>
 <li><strong>Web ページを置き換える動物の画像をパッケージ化</strong><br />
  画像を "web-accessible なリソース" とし、Web ページから参照できるようにします。</li>
</ul>

<p>このアドオンは次のような全体構成になっています。</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/12293/beastify-anatomy.svg" style="display:block; height:754px; margin-left:auto; margin-right:auto; width:500px" /></p>

<p>このアドオンはシンプルですが、WebExtensions API の基本的なコンセプトを多く含んでいます。</p>

<ul>
 <li>ツールバーにボタンを追加する</li>
 <li>HTML / CSS / JavaScript を用いてポップアップのパネルを定義する</li>
 <li>Web ページに content script を差し込む</li>
 <li>拡張機能の中において content script と他のスクリプトとを通信させる</li>
 <li>Web ページで用いるリソースをアドオンにパッケージ化する</li>
</ul>

<p><a href="https://github.com/mdn/webextensions-examples/tree/master/beastify">ソースコード一式は GitHub で参照できます</a>。</p>

<h2 id="WebExtension_を書く">WebExtension を書く</h2>

<p>新しいディレクトリを作成し、そのディレクトリに移動します。</p>

<pre class="brush: bash">
mkdir beastify
cd beastify</pre>

<h3 id="manifest.json">manifest.json</h3>

<p>それでは、"beastify" ディレクトリ配下に新しいファイル "manifest.json" を作成します。以下の内容を書き込んで保存してください。</p>

<pre class="brush: json line-numbers  language-json">
<code class="language-json"><span class="punctuation token">{</span>

  <span class="key token">"manifest_version":</span> <span class="number token">2</span><span class="punctuation token">,</span>
  <span class="key token">"name":</span> <span class="string token">"Beastify"</span><span class="punctuation token">,</span>
  <span class="key token">"version":</span> <span class="string token">"1.0"</span><span class="punctuation token">,</span>

  <span class="key token">"description":</span> <span class="string token">"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"</span><span class="punctuation token">,</span>
  <span class="key token">"homepage_url":</span> <span class="string token">"https://github.com/mdn/webextensions-examples/tree/master/beastify"</span><span class="punctuation token">,</span>
  <span class="key token">"icons":</span> <span class="punctuation token">{</span>
    <span class="key token">"48":</span> <span class="string token">"icons/beasts-48.png"</span>
  <span class="punctuation token">}</span><span class="punctuation token">,</span>

  <span class="key token">"applications":</span> <span class="punctuation token">{</span>
    <span class="key token">"gecko":</span> <span class="punctuation token">{</span>
      <span class="key token">"id":</span> <span class="string token">"[email protected]"</span><span class="punctuation token">,</span>
      <span class="key token">"strict_min_version":</span> <span class="string token">"45.0"</span>
    <span class="punctuation token">}</span>
  <span class="punctuation token">}</span><span class="punctuation token">,</span>

  <span class="key token">"permissions":</span> <span class="punctuation token">[</span>
    <span class="string token">"activeTab"</span>
  <span class="punctuation token">]</span><span class="punctuation token">,</span>

  <span class="key token">"browser_action":</span> <span class="punctuation token">{</span>
    <span class="key token">"default_icon":</span> <span class="string token">"icons/beasts-32.png"</span><span class="punctuation token">,</span>
    <span class="key token">"default_title":</span> <span class="string token">"Beastify"</span><span class="punctuation token">,</span>
    <span class="key token">"default_popup":</span> <span class="string token">"popup/choose_beast.html"</span>
  <span class="punctuation token">}</span><span class="punctuation token">,</span>

  <span class="key token">"web_accessible_resources":</span> <span class="punctuation token">[</span>
    <span class="string token">"beasts/frog.jpg"</span><span class="punctuation token">,</span>
    <span class="string token">"beasts/turtle.jpg"</span><span class="punctuation token">,</span>
    <span class="string token">"beasts/snake.jpg"</span>
  <span class="punctuation token">]</span>

<span class="punctuation token">}</span></code></pre>

<ul>
 <li>最初の 3 つのキー <code><a href="https://developer.mozilla.org/ja/Add-ons/WebExtensions/manifest.json/manifest_version">manifest_version</a></code>、<code><a href="https://developer.mozilla.org/ja/Add-ons/WebExtensions/manifest.json/name">name</a></code>、<code><a href="https://developer.mozilla.org/ja/Add-ons/WebExtensions/manifest.json/version">version</a></code> は必須であり、アドオンの基本的なメタデータを指定します。</li>
 <li><code><a href="https://developer.mozilla.org/ja/Add-ons/WebExtensions/manifest.json/description">description</a></code> は省略可能ですが、設定しておくことをお勧めします。この値はアドオンマネージャに表示されます。</li>
 <li><code><a href="https://developer.mozilla.org/ja/Add-ons/WebExtensions/manifest.json/icons">icons</a></code> は省略可能ですが、 設定しておくことをお勧めします。この値はアドオンのアイコンを指定するものであり、アイコンはアドオンマネージャに表示されます。</li>
 <li><code><a href="https://developer.mozilla.org/ja/Add-ons/WebExtensions/manifest.json/applications">applications</a></code> は(Chrome 拡張機能と異なり)Firefox における必須項目であり、アドオンの ID を指定します。他にも、アドオンがサポートする Firefox のバージョンについて、最小値・最大値を指定することが可能です。</li>
 <li><code><a href="https://developer.mozilla.org/ja/Add-ons/WebExtensions/manifest.json/permissions">permissions</a></code> はアドオンに必要なパーミッションのリストです。ここでは <a href="https://developer.mozilla.org/ja/Add-ons/WebExtensions/manifest.json/permissions#activeTab_permission"><code>activeTab</code> パーミッション</a> を要請しています。</li>
 <li><code><a href="https://developer.mozilla.org/ja/Add-ons/WebExtensions/manifest.json/browser_action">browser_action</a></code> はツールバーのボタンを指定するものです。ここでは 3 つの情報を指定しています。
  <ul>
   <li><code>default_icon</code> ではボタンのアイコンを指定します(必須項目)。</li>
   <li><code>default_title</code> ではツールチップの文字列を指定します(省略可)。</li>
   <li><code>default_popup</code> ではユーザがボタンをクリックした際に表示されるポップアップを指定します。今回はポップアップを表示させたいので、アドオンに含める HTML ファイルを <code>defualt_popup</code> キーで指定しています。</li>
  </ul>
 </li>
 <li><code><a href="https://developer.mozilla.org/ja/Add-ons/WebExtensions/manifest.json/web_accessible_resources">web_accessible_resources</a></code> は Web ページからアクセスしたいファイルのリストです。このアドオンでは、拡張機能に同梱した画像で Web ページを置き換えるため、画像を Web ページからアクセス可能にする必要があります。</li>
</ul>

<p>パスはすべて manifest.json 自身からの相対パスで指定することに注意してください。</p>

<h3 id="The_icon">アイコン</h3>

<p>アドオンにはアイコンを用意すると良いでしょう。このアイコンは、アドオンマネージャでアドオンのリスト横に表示されます(アドオンマネージャは "about:addons" の URL から確認できます)。 今回の manifest.json では "icons/beasts-48.png" を用意していると宣言しています。</p>

<p>まずは "beastify" ディレクトリの下に "icons" ディレクトリを作成します。次に、アイコンを "border-48.png" という名前で "icons" ディレクトリ内に保存します。必要であれば <a class="external external-icon" href="https://github.com/mdn/webextensions-examples/blob/master/beastify/icons/beasts-48.png">サンプルで使用しているアイコン</a> を利用しても構いません(このアイコンは <a href="https://www.iconfinder.com/iconsets/free-retina-icon-set">Aha-Soft’s Free Retina iconset</a> から引用したものであり、該当する <a href="https://www.aha-soft.com/free-icons/free-retina-icon-set/">ライセンス</a> の下で使用しています)。</p>

<p>ここでアイコンを自分で用意する場合は 48x48 ピクセルのサイズにする必要があります。高解像度のディスプレイには 96x96 ピクセルのアイコンを表示させたい場合は、manifest.json の <code>icons</code> オブジェクトに <code>96</code> というプロパティで設定してください。</p>

<pre class="brush: json line-numbers  language-json">
<code class="language-json"><span class="key token">"icons":</span> <span class="punctuation token">{</span>
  <span class="key token">"48":</span> <span class="string token">"icons/beasts-48.png"</span><span class="punctuation token">,</span>
  <span class="key token">"96":</span> <span class="string token">"icons/beasts-96.png"</span>
<span class="punctuation token">}</span></code></pre>

<h3 id="ツールバーボタン">ツールバーのボタン</h3>

<p>ツールバーのボタンにもアイコンが必要です。 今回の manifest.json では "button/beasts.png" を用意していると宣言しています。</p>

<p>まずは "beastify" ディレクトリの下に "button" ディレクトリを作成します。次に、アイコンを "beasts.png" という名前で "button" ディレクトリ内に保存します。必要であれば <a class="external external-icon" href="https://github.com/mdn/webextensions-examples/blob/master/beastify/button/beasts.png">サンプルで使用しているアイコン</a> を利用しても構いません(このアイコンは <a href="https://www.iconbeast.com/free">IconBeast Lite のアイコン集</a>  から引用したものであり、該当する <a href="https://www.iconbeast.com/faq/">ライセンス</a> の下で使用しています)。</p>

<p>ポップアップを使わない場合、ユーザがボタンをクリックした際にはクリックイベントがアドオンに向けて送出されます。ポップアップを使う場合にクリックイベントは送出されず、代わりにポップアップが開きます。今回はポップアップが必要なので、次の項で作成しましょう。</p>

<h3 id="ポップアップ">ポップアップ</h3>

<p>今回のポップアップでは、ユーザが 3 つの動物から 1 つ選択できる機能を持つこととします。</p>

<p>アドオンのルート配下に "popup" というディレクトリを新しく作成します。ここにはポップアップ用のコードを保管します。ポップアップは次の 3 ファイルから構成されます。</p>

<ul>
 <li><strong><code>choose_beast.html</code></strong> パネルのコンテンツを定義する</li>
 <li><strong><code>choose_beast.css</code></strong> コンテンツのスタイルを指定する</li>
 <li><strong><code>choose_beast.js</code></strong> アクティブなタブで content script を実行し、ユーザの選択を処理する</li>
</ul>

<h4 id="choose_beast.html">choose_beast.html</h4>

<p>HTML ファイルは次のようになります。</p>

<pre class="brush: html">
&lt;!DOCTYPE html&gt;

&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset="utf-8"&gt;
    &lt;link rel="stylesheet" href="choose_beast.css"/&gt;
  &lt;/head&gt;

  &lt;body&gt;
    &lt;div class="beast"&gt;Frog&lt;/div&gt;
    &lt;div class="beast"&gt;Turtle&lt;/div&gt;
    &lt;div class="beast"&gt;Snake&lt;/div&gt;

    &lt;script src="choose_beast.js"&gt;&lt;/script&gt;
  &lt;/body&gt;

&lt;/html&gt;</pre>

<p>単にここでは動物ごとに要素を与えています。通常の Web ページと同じように CSS と JS ファイルを読み込んでいることに注意してください。</p>

<h4 id="choose_beast.css">choose_beast.css</h4>

<p>この CSS ではポップアップのサイズを固定、3 つの選択肢で空白を埋めることを保証し、基本的なスタイリングを与えます。</p>

<pre class="brush: css line-numbers  language-css">
<code class="language-css"><span class="selector token">html, body </span><span class="punctuation token">{</span>
  <span class="property token">width</span><span class="punctuation token">:</span> <span class="number token">100</span>px<span class="punctuation token">;</span>
<span class="punctuation token">}</span>

<span class="selector token"><span class="class token">.beast</span> </span><span class="punctuation token">{</span>
  <span class="property token">margin</span><span class="punctuation token">:</span> <span class="number token">3%</span> auto<span class="punctuation token">;</span>
  <span class="property token">padding</span><span class="punctuation token">:</span> <span class="number token">4</span>px<span class="punctuation token">;</span>
  <span class="property token">text-align</span><span class="punctuation token">:</span> center<span class="punctuation token">;</span>
  <span class="property token">font-size</span><span class="punctuation token">:</span> <span class="number token">1.5</span>em<span class="punctuation token">;</span>
  <span class="property token">background-color</span><span class="punctuation token">:</span> <span class="hexcode token">#E5F2F2</span><span class="punctuation token">;</span>
  <span class="property token">cursor</span><span class="punctuation token">:</span> pointer<span class="punctuation token">;</span>
<span class="punctuation token">}</span>

<span class="selector token"><span class="class token">.beast</span><span class="pseudo-class token">:hover</span> </span><span class="punctuation token">{</span>
  <span class="property token">background-color</span><span class="punctuation token">:</span> <span class="hexcode token">#CFF2F2</span><span class="punctuation token">;</span>
<span class="punctuation token">}</span></code></pre>

<h4 id="choose_beast.js">choose_beast.js</h4>

<p>ポップアップ用の JavaScript ではクリックイベントをリッスンします。3 つの動物のどれかがクリックされた場合、アクティブなタブに content script を差し込みます。content script が読み込まれると、動物の選択のメッセージを送ります:</p>

<pre class="brush: js line-numbers  language-js">
<code class="language-js"><span class="comment token" spellcheck="true">/*
動物の名前を受け取り、対応する画像の URL を返す
*/</span>
<span class="keyword token">function</span> <span class="function token">beastNameToURL</span><span class="punctuation token">(</span>beastName<span class="punctuation token">)</span> <span class="punctuation token">{</span>
  <span class="keyword token">switch</span> <span class="punctuation token">(</span>beastName<span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">case</span> <span class="string token">"Frog"</span><span class="punctuation token">:</span>
      <span class="keyword token">return</span> chrome<span class="punctuation token">.</span>extension<span class="punctuation token">.</span><span class="function token">getURL</span><span class="punctuation token">(</span><span class="string token">"beasts/frog.jpg"</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
    <span class="keyword token">case</span> <span class="string token">"Snake"</span><span class="punctuation token">:</span>
      <span class="keyword token">return</span> chrome<span class="punctuation token">.</span>extension<span class="punctuation token">.</span><span class="function token">getURL</span><span class="punctuation token">(</span><span class="string token">"beasts/snake.jpg"</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
    <span class="keyword token">case</span> <span class="string token">"Turtle"</span><span class="punctuation token">:</span>
      <span class="keyword token">return</span> chrome<span class="punctuation token">.</span>extension<span class="punctuation token">.</span><span class="function token">getURL</span><span class="punctuation token">(</span><span class="string token">"beasts/turtle.jpg"</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
  <span class="punctuation token">}</span>
<span class="punctuation token">}</span>

<span class="comment token" spellcheck="true">/*
ポップアップのクリックイベントをリッスンする。

動物以外がクリックされた場合は最初で return する。

そうでない場合、クリックされたノードの textContent から動物の名前を取得する。

アクティブなタブに content script "beastify.js" を差し込む。

続いて、アクティブなタブへの参照を取得し、"beastify.js" にメッセージを送信する。
このメッセージには、選択された動物に対応する画像の URL を含んでいる。
*/</span>
document<span class="punctuation token">.</span><span class="function token">addEventListener</span><span class="punctuation token">(</span><span class="string token">"click"</span><span class="punctuation token">,</span> <span class="keyword token">function</span><span class="punctuation token">(</span>e<span class="punctuation token">)</span> <span class="punctuation token">{</span>
  <span class="keyword token">if</span> <span class="punctuation token">(</span><span class="operator token">!</span>e<span class="punctuation token">.</span>target<span class="punctuation token">.</span>classList<span class="punctuation token">.</span><span class="function token">contains</span><span class="punctuation token">(</span><span class="string token">"beast"</span><span class="punctuation token">)</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">return</span><span class="punctuation token">;</span>
  <span class="punctuation token">}</span>

  <span class="keyword token">var</span> chosenBeast <span class="operator token">=</span> e<span class="punctuation token">.</span>target<span class="punctuation token">.</span>textContent<span class="punctuation token">;</span>
  <span class="keyword token">var</span> chosenBeastURL <span class="operator token">=</span> <span class="function token">beastNameToURL</span><span class="punctuation token">(</span>chosenBeast<span class="punctuation token">)</span><span class="punctuation token">;</span>

  chrome<span class="punctuation token">.</span>tabs<span class="punctuation token">.</span><span class="function token">executeScript</span><span class="punctuation token">(</span><span class="keyword token">null</span><span class="punctuation token">,</span> <span class="punctuation token">{</span>
    file<span class="punctuation token">:</span> <span class="string token">"/content_scripts/beastify.js"</span>
  <span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span>

  chrome<span class="punctuation token">.</span>tabs<span class="punctuation token">.</span><span class="function token">query</span><span class="punctuation token">(</span><span class="punctuation token">{</span>active<span class="punctuation token">:</span> <span class="keyword token">true</span><span class="punctuation token">,</span> currentWindow<span class="punctuation token">:</span> <span class="keyword token">true</span><span class="punctuation token">}</span><span class="punctuation token">,</span> <span class="keyword token">function</span><span class="punctuation token">(</span>tabs<span class="punctuation token">)</span> <span class="punctuation token">{</span>
    chrome<span class="punctuation token">.</span>tabs<span class="punctuation token">.</span><span class="function token">sendMessage</span><span class="punctuation token">(</span>tabs<span class="punctuation token">[</span><span class="number token">0</span><span class="punctuation token">]</span><span class="punctuation token">.</span>id<span class="punctuation token">,</span> <span class="punctuation token">{</span>beastURL<span class="punctuation token">:</span> chosenBeastURL<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
  <span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span>

<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>

<p>ここでは 3 つの WebExtension API メソッドを使用しています。</p>

<ul>
 <li><strong><code>chrome.tabs.executeScript</code></strong> は "content_scripts/beastify.js" にあるコンテントスクリプトをアクティブなタブに注入します</li>
 <li><strong><code>chrome.tabs.query</code></strong> はアクティブなタブを取得します</li>
 <li><strong><code>chrome.tabs.sendMessage</code></strong> はアクティブなタブ内で実行されるコンテントスクリプトにメッセージを送ります。メッセージは <code>beast</code> プロパティにある選択した動物が入っています。</li>
</ul>

<h3 id="コンテントスクリプト">コンテントスクリプト</h3>

<p>拡張機能のルートフォルダの下に、"content_scripts" という名のディレクトリを新規作成し、その中に "beastify.js" という名のファイルを作成し、下記のコンテンツを記述します:</p>

<pre class="brush: 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");
  }
}

</pre>

<p>コンテントスクリプトは拡張機能からの(特に、上記 "choose_beast.js" からの)メッセージに対するリスナーを追加します リスナー内で、これは次のことを行います:</p>

<ul>
 <li><code>document.body 内のすべての要素を削除します。</code></li>
 <li>動物名を、画像を指定する URL に変換します。</li>
 <li>URLを指定する <code>&lt;img&gt;</code> 要素を作り、DOM に挿入する</li>
 <li>メッセージリスナを削除する</li>
</ul>

<h3 id="動物">動物</h3>

<p>最後に、動物の画像を入れておく必要があります。</p>

<p>"beasts" という名のディレクトリを作成し、その中に3つの画像を、適切な名前をつけて追加します。<a href="https://github.com/mdn/webextensions-examples/tree/master/beastify/beasts">GitHub リポジトリ</a>から画像を取得できます、あるいはここからでも:</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/11459/frog.jpg" style="display:inline-block; height:200px; margin:20px; width:200px" /><img alt="" src="https://mdn.mozillademos.org/files/11461/snake.jpg" style="display:inline-block; height:200px; margin:20px; width:200px" /><img alt="" src="https://mdn.mozillademos.org/files/11463/turtle.jpg" style="display:inline-block; height:200px; margin:20px; width:200px" /></p>

<h2 id="パッケージ化とインストール">パッケージ化とインストール</h2>

<p>正しいファイルが正しい場所にあるかどうか、再チェックします:</p>

<pre>
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</pre>

<p>Firefox 拡張機能は XPI ファイルとしてパッケージ化されます、これは単に"xpi" の拡張子つきのZIPファイルです。</p>

<p>つまづきポイントとしては、ZIP ファイルは拡張機能の中のファイルを、一つのZIPにしたものである必要があり、格納ディレクトリをZIP化したものではありません。なので動物化のファイルから、一つのXPIを作るには、 コマンドシェルで"beastify" ディレクトリに移動して、次のようにタイプします:</p>

<pre class="brush: bash">
   # in beastify/
   zip -r ../beastify.xpi *</pre>

<p>XPI をインストールするには、単に Firefox で開きます:</p>

<ul>
 <li>ファイルメニューから開くを選ぶ、または Ctrl/Cmd+O を押す</li>
 <li>選択ダイアログから "beastify.xpi" を選択する</li>
</ul>

<p>署名されていない拡張機能をインストールする旨の警告が出るでしょう、警告を受諾します。</p>

<p>Firefoxツールバーにアイコンが出現するのが見えるでしょう。webページを開いて、アイコンをクリックし、動物を選択すると、webページの画像が変化するのが見えます。</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>
このリビジョンへ戻す