OXY NOTES

Firefox機能拡張でツールバーボタンを作成する方法

機能拡張の構成に必要なファイルを確認しながら、ツールバーボタンを実装します

Firefox機能拡張の解説」第2弾。

このページでは機能拡張を構成するファイルを把握し、実際に動作する機能拡張を作成します。

合わせて機能拡張の動作テストをする方法や、デバックの方法も解説します。


このページの目次


パッケージマニフェストについて

前回作成した機能拡張のディレクトリにある「package.json」というファイルです。このファイルだけでも機能拡張として動作します。
パッケージマニフェストには機能拡張に関するタイトルや作者情報などのメタ情報を記載します。

jpm initコマンド」で何も入力しないで追加される項目は以下の通り。

{
  "title": "hoge Addon",
  "name": "my-addon",
  "version": "0.0.1",
  "description": "A basic add-on",
  "main": "index.js",
  "author": "",
  "engines": {
    "firefox": ">=38.0a1",
    "fennec": ">=38.0a1"
  },
  "license": "MIT"
}

package_jsonの公式ページ

公式ページに注釈がありますが、JPMになってから多くの項目が統廃合されています。古い解説ページを参考にしている場合は注意してください。


アドオンスクリプトについて

JPMで作成したサンプルでは「index.js」というファイルが作成されます。このファイルがエントリーポイントになります。エントリーポイントとは最初に実行されるファイルです。
ちなみに公式の解説では他のJavaScriptファイルと区別してAdd-on script(アドオンスクリプト)と名付けているようです。

以前のcfxコマンドではデフォルトでlibフォルダに作成されるmain.jsというファイルがアドオンスクリプトでした。2015年現在、アドオンスクリプトの解説にはmain.jsというファイル名が使われていることが多いので注意してください。

アドオンスクリプトの名前やフォルダは変更することができます。例えばhoge.jsというファイルをアドオンスクリプトにする場合はパッケージマニフェストに以下のように記述します。

"main": "hoge.js"

README.mdについて

拡張子から分かる通りマークダウン記法のリードミーファイル。githubなどでよく使われていますね。
これはオプションで無くても構いません。

余談ですがREADMEが大文字なのはASCII文字コード順で先頭に来るようにするためらしいです。

README のファイル名が大文字である理由 – clock-up-blog


その他のファイルについて

jpm initで機能拡張を作成するとtestフォルダtest-index.jsというファイルが作成されます。
内容については触れませんが、このようにディレクトリを作成して読み込むことができるので、構造が複雑になる場合はimageディレクトリlibディレクトリを作って分類すると必要なファイルが探しやすいと思います。

cfxコマンドの時代にはdataフォルダの中にimageやlibといったフォルダを作成して管理するのが一般的でした。


機能拡張のチュートリアルについて

日本語版のチュートリアルや解説もあるのですが、Firefoxの革新性ゆえか情報の陳腐化が激しく、まともに動作する解説がありません。

そのため不慣れでも英語版のチュートリアルを進めるのをお勧めします。

英語版の公式チュートリアル

書いてある通りに進めても動作しない日本語版の公式チュートリアル

cfxコマンド時代のものですがFirefoxの機能拡張についてまとめた神スライド

上記3点を見比べながら進めれば問題なく作成できると思います。
と、それだけでは手抜きなので、JPMを利用して英語版のチュートリアルにある機能拡張を作成してみます。


ツールバーボタンを追加する

ツールバーボタンを追加する機能拡張を作成します。
まずはコマンドプロンプトを立ち上げCドライブ直下にToolbar Add-onを作成します。

$ cd C:\
$ mkdir Toolbar-Addon
$ cd Toolbar-Addon
$ jpm init

title: (My Jetpack Addon) Toolbar Addon ←タイトル
name: Toolbar Addon ←名前
version: (0.0.1)
description: (A basic add-on) ツールバーをテストするAdd-on ←解説
entry point: (index.js)
author: Oxy ←作者名
engines (comma separated): (firefox,fennec)
license: (MIT)
JPM undefined About to write to C:\package.json:

{
  "title": "Toolbar Addon",
  "name": "toolbaraddon",
  "version": "0.0.1",
  "description": "ツールバーをテストするAdd-on",
  "main": "index.js",
  "author": "Oxy",
  "engines": {
    "firefox": ">=38.0a1",
    "fennec": ">=38.0a1"
  },
  "license": "MIT"
}


Is this ok? (yes) y ←YESを表すyを入力してエンター

これでCドライブ直下にToolbar-Addonという機能拡張が作成されました。

アイコン用の画像を用意する

ツールバーには3つのサイズの画像を指定します。
チュートリアルに習って以下のファイル名でテスト用の画像を作ります。Google Chromeの解説の時と同じようにtestのTというアイコンを作成しました。
用意するのが面倒だという方は以下の画像を使ってください。

ファイル ファイル名 用途
icon-16.png トグルボタン用
icon-32.png カスタマイズ画面用
icon-64.png メニューパネル用(どこかは不明)

C:\Toolbar-Addon\に保存しておいてください。

アドオンスクリプトを編集する

エントリーファイルであるアドオンスクリプト「index.js」を編集します。
手抜きですが、チュートリアルの記述をそのまま拝借します。

var buttons = require('sdk/ui/button/action');
var tabs = require("sdk/tabs");

var button = buttons.ActionButton({
	id: "mozilla-link",
	label: "Visit Mozilla",
	icon: {
		"16": "./icon-16.png",
		"32": "./icon-32.png",
		"64": "./icon-64.png"
	},
	onClick: handleClick
});

function handleClick(state) {
	tabs.open("https://www.mozilla.org/");
}

1~2行目requireでモジュールを読み込みます。
この例ではボタンアクションに関するAPIであるui/button/actionモジュールと、タブに関するAPIであるsdk/tabsモジュールを読み込んでいます。こうして読み込まれるモジュールをSDKモジュールと呼びます。

Google Chromeだとマニフェストファイルに使用するAPIを指定していましたが、Firefoxはアドオンスクリプトに直接書くタイプです。

実際に読み込まれるモジュールはFirefoxで以下のURLを入力すると表示できます。
resource://gre/modules/commonjs/sdk/ui/button/action.js
resource://gre/modules/commonjs/sdk/tabs.js

バージョンの違いによるrequireの違い

古いバージョンだと「sdk/」の部分がいらず、require("tabs")で動作していましたが、今では警告が出ます。

また、過去にはモジュールの呼び出しにconstを利用して定数に代入していました。

現在ではvarで定義して、require("sdk/tabs")といった記述になったので、古い解説を参考にする際には注意してください。

APIの種類

APIにはHigh-Level APIsLow-Level APIsがあります。
今回の例で言う「tabs」はHigh-Level APIs
ui/button/action」はLow-Level APIsです。

High-Level APIs互換性を保証されたモジュールです。
対してLow-Level APIsは新しく付けられた実験的な機能や、将来変更されたり、無くなる可能性のあるモジュールです。

長く使える機能拡張を目指すにはHigh-Level APIsを優先的に使いましょう。

各モジュールに関する説明は以下のページにあります。
数が膨大ですが、それぞれ1行程度の解説があるので、ざっと目を通しておくと、どんな機能を利用できるのか把握できます。

公式のLow-Level APIsのページ

公式のHigh-Level APIsのページ

3行目~12行目までActionButtonのオプションを指定しています。
指定するオプションの詳細についてはドキュメントを見るのが一番です。
どんなオプションを指定することができて、どんなメソッドが使えるかが豊富なサンプルと共に紹介されています。

公式のui/button/action解説ページ

今回の例で言えばidlabeliconRequired optionsとなっているので必須であることがわかります。

4行目var buttonとして代入しているのはbutton.click()等として、click()メソッドを使ったりすることができるからです。このメソッドを使うと作成したボタンをクリックしたのと同じように動作させることができます。

また以下のようにActionButtonを直接読み込んでオプションを指定することもできます。モジュールのメソッドなどを利用しない場合は、この書き方の方が簡単ですね。

var { ActionButton } = require("sdk/ui/button/action");

ActionButton({
	id: "mozilla-link",
	label: "Visit Mozilla",
	icon: {
		"16": "./icon-16.png",
		"32": "./icon-32.png",
		"64": "./icon-64.png"
	},
	onClick: handleClick
});

12行目onClickとありますが、こちらはtypefunctionとあります。解説にはクリックイベントのハンドラーとあるので、ボタンをクリックした時に実行される関数を指定することがわかります。
ここではhandleClickという関数を指定しています。「()(カッコ)」はいらないので注意してください。

15~17行目、関数handleClickを定義して、tabsモジュールopenという関数にURLを指定しています。

tabsモジュールの解説

openは多くのオプションを指定できることがわかります。
第2引数にinBackground: trueとすれば、バックグラウンドで開いたり、onOpenタブを開いたハンドラーとして関数を実行することができたりと、実用的なオプションが用意されています。

バックグラウンドで新しいタブを開く例

function handleClick(state) {
	tabs.open({
		url: "https://www.mozilla.org/",
		inBackground: true
	});
}

jpm runで機能拡張を実行する

jpm runを利用して機能拡張を実行します。

$ jpm run
JPM undefined Starting jpm run on Toolbar Addon
Creating XPI
JPM undefined XPI created at C:\Users\tobikko\AppData\Local\Temp\@toolbaraddon-0
.0.1.xpi (64ms)
Created XPI at C:\Users\tobikko\AppData\Local\Temp\@toolbaraddon-0.0.1.xpi
JPM undefined Creating a new profile

するとFirefoxが自動で立ち上がります。

ツールバーのアイコンをマウスオーバーするとlabelに指定したVisit Mozillaが表示されます。

クリックすると新しいタブでMozillaのページが開きます。

Firefoxのウィンドウを閉じると、コマンドプロンプトが入力待ちの状態に戻ります。

更新作業をした場合は1度ウィンドウを閉じてrunをもう一度実行し直す必要があります。


jpm watchpostで機能拡張を実行する

せっかく用意されているので実際に使ってみましょう。
前回の投稿で解説しましたが、Extension Auto-Installerが必要なのでインストールしていない方はインストールしておいてください。

$ jpm watchpost --post-url http://localhost:8888/

この状態でFirefoxを立ち上げます。するとTと書かれたアイコンが表示されると思います。

このウィンドウを開いたまま「index.js」を以下のように編集して、保存してください。

var buttons = require('sdk/ui/button/action');
var tabs = require("sdk/tabs");

var button = buttons.ActionButton({
	id: "mozilla-link",
	label: "Visit Mozilla",
	icon: {
		"16": "./icon-16.png",
		"32": "./icon-32.png",
		"64": "./icon-64.png"
	},
	onClick: handleClick
});


function handleClick(state) {
	tabs.open({
		url: "https://www.mozilla.org/",
		inBackground: true
	});
}

すると以下の様なログが流れます。

JPM undefined Starting jpm post on Toolbar Addon
Creating XPI
JPM undefined XPI created at C:\Toolbar-Addon\@toolbaraddon-0.0.1.xpi (67ms)
Created XPI at C:\Toolbar-Addon\@toolbaraddon-0.0.1.xpi
Successfully created xpi at C:\Toolbar-Addon\@toolbaraddon-0.0.1.xpi
Posted XPI to http://localhost:8888/
Removed XPI from C:\Toolbar-Addon\@toolbaraddon-0.0.1.xpi

ブラウザのツールバーボタンをクリックしてみてください。

新しいタブがバックグラウンドで開いたと思います。このようにjpm watchpostを利用するとリアルタイムに変更点を確認することができます。

1点だけ注意点があり、公式ドキュメントにもありますが、console.log()コマンドプロンプトにログを出力をすることはできません。その場合はjpm runを使ってください。

jpm watchpostでログを確認するにはFirefox自体のログを確認できるBrowser Console (Ctrl+Shift+J)で出力を確認します。
右クリックから表示できるWebコンソールでは出力できないので注意してください。


今回は実際に機能拡張を作ってみました。
流れで理解すると、開発のしやすい便利な機能が盛りだくさんなことが理解していただけたと思います。

次のページはしっかり理解しておかないとハマりやすい「Firefox機能拡張のポップアップとコンテンツスクリプトについて」です。