Firefoxのアドオンを書いてみた

word-later というアドオンを作りました( github )。これは英語の文章を読む時に知らない単語が出たらポチポチ登録して、読み終えた後で単語帳につっこむために単語一覧を表示するアドオンです。探せば同じようなアドオンはあるかと思いますが勉強も兼ねて。

昔もアドオンを作ろうとしたことがあるのですが、結構大変な作業でした。 今はAdd-on SDKなるものが登場して、ある程度のことは簡単に作れるようになってます。本家のチュートリアル を参考に環境構築まではとても簡単にできました。

以下、今回使ったAddonで使えるUIなどについてメモ

ActionButton

ツールバーのボタンです、Firefox 29以降のUIではツールバーのアイコンをメニューパネル(右上の横棒3つのやつで開くところ)に配置可能になりました。 メニューパネルではボタンのアイコンは大きく表示されるので、iconプロパティは各サイズ用意したほうがいいと思います。

var button = require("sdk/ui/button/action").ActionButton({
    id: "word-later",
    label: "word later",
    icon: {
        "16": "./wordlater_icon16.png",
        "32": "./wordlater_icon32.png",
        "64": "./wordlater_icon64.png",
    },
    onClick: function(state) {
        ...
    },
});

context-menu

右クリックで出てくるコンテキストメニューです。 今回のように何かを選択したときにメニューに項目を出したい場合はcontextプロパティにSelectionContext()を指定すればいいです。 "〜を検索"のように、選択されたテキストをメニューに追加する場合

var contextMenu = require("sdk/context-menu");
var menuItem = contextMenu.Item({
    label: "WORD LATER",
    context: contextMenu.SelectionContext(),
    contentScript:
    'self.on("context", function () {' +
    '  var text = window.getSelection().toString();' + //選択された文字列を取得
    '  if (text.length > 20) text = text.substr(0, 20) + "...";' + //あまりに長い文章が選択された場合は省略
    '  return "Add word-later :" + text;' + //メニューに表示するテキスト
    '});'
    ...
});

のように書けばできます。contextScriptプロパティにはコードの文字列を与えないといけないのが注意点です。javascriptには複数行文字列が無いので汚い書き方になりますが仕方ないですね。

sidebar

サイドバーはそれ自体がひとつのHTMLのページになります。もちろん、その中でCSS, javascriptも使用可能です。 サイドバーとアドオンの通信には"addon"というグローバル変数を通しておこなうことができます。addon.port.emit()で相手側に送信しaddon.port.on()でハンドリングする流れです。

var sidebar = require("sdk/ui/sidebar").Sidebar({
    id: "word-later-list",
    title: "Word Later",
    url: require("sdk/self").data.url("sidebar.html"),

    onAttach: function (worker) {
        ...
    },
    onDetach: function () {
        ...
    },

    onReady: function(worker) { // "worker"がサイドバーの"addon"とつながる
        ...
        worker.port.on("delete", function(item) {
            //addon.port.emit("delete", item)が呼ばれたら
            ...
        });
        ...
    },
});

としておけば、サイドバー側で

addon.port.emit("delete", item);

を呼び出すことでアドオン側に処理をさせることができます。 逆に、サイドバー側でaddon.port.on()で設定して、それをアドオン側から呼び出すこともできます。

simple-storage

データを保存することができます。 データを保存するという点では似たようなものにsimple-prefsというモジュールがあります。 各種設定などはsimple-prefs、ただのデータはsimple-storageと使い分けすればいいと思います。

var simple_storage = require("sdk/simple-storage");
simple_storage.storage.foo = 1;
// simple_storage.foo = 1; // NG
...

このようにrequire("sdk/simple-storage")で取ってきたオブジェクトのstorageプロパティに保存したいデータを自由に格納できます。 storageプロパティに入れないとだめなので気をつけてください。 データは配列、真偽値、数字、オブジェクト、null、文字列が格納できます。まあ、何でも入れられると思って問題なさそうです。

おわり

凝ったことをしない限りはとても簡単にアドオンを作ることができます。ドキュメントも英語ですが、きちんと揃ってるので頑張って読み進めていけばそれほど困ることは無いと思います。 この後スマホ版のアドオンも作りたいなーと思ったのですが、使えるモジュールがかなり少なく、まだ仕様が固まってないような雰囲気なのでどうしようかなと思案中。

Comments