私の歴史と今

振り返ると恥ずかしくなるのが私の歴史。だけどそのときは真面目に書いていた訳でね。そんな今の私を書いていく。

Firefox拡張機能をcfxを使って作る

次期バージョンのFirefox38からはNode.jsベースの新しい仕組みjpmが用意されるそうだけど、今まで古いxul形式の拡張機能を使ってきたので現行のpythonベースのcfxを使ってみた。

基本、以下のページの通りやっていけばいい。

developer.mozilla.org

cfxは以下の環境で使用可能だが、今回はMac Yosemite環境で使用してみた。

Python

cfxはPythonベースなので、Pythonが必要。ただし、Macには既にインストールされているので不要。

なお、Python2系でしか動作しないみたい。今回の環境は2.7.6だった。

$ python --version
Python 2.7.6

インストール

ここからダウンロードしてインストールする。 Installation - Mozilla | MDN

*でも、最終的にはHomebrewでインストールしました(後述)

$ mkdir ~/mozilla
$ cd ~/mozilla
$ tar -xf addon-sdk-1.17.tar.gz 
$ ln -s addon-sdk-1.17 addon-sdk
$ cd addon-sdk
$ ls -l
-rw-r--r--@   1 junya  staff   800  7 15  2014 LICENSE
-rw-r--r--@   1 junya  staff  1189  7 15  2014 README
drwxr-xr-x@   5 junya  staff   170  7 15  2014 app-extension
drwxr-xr-x@  10 junya  staff   340  7 15  2014 bin
drwxr-xr-x@   7 junya  staff   238  7 15  2014 examples
drwxr-xr-x@   8 junya  staff   272  7 15  2014 lib
-rw-r--r--@   1 junya  staff  2556  7 15  2014 mapping.json
-rw-r--r--@   1 junya  staff   269  7 15  2014 package.json
drwxr-xr-x@   7 junya  staff   238  7 15  2014 python-lib
drwxr-xr-x@ 155 junya  staff  5270  7 15  2014 test

シェルの確認

$ echo $SHELL
/bin/bash

開発する時は、毎回下記のアクティベート作業が必要らしい。

$ source bin/activate
Welcome to the Add-on SDK. For the docs, visit https://addons.mozilla.org/en-US/developers/docs/sdk/latest/

永続的に設定したい場合はPATHにcfxを通す。

ln -s ~/mozilla/addon-sdk/bin/cfx /usr/local/bin/cfx

と、ここまで来てわかったが、Homebrewでインストールすれば上記の作業などすべてが不要。。。ということで、削除してHomebrewでインストールした。

$ rm -f /usr/local/bin/cfx
$ rm -rf ~/mozilla
$ brew update
$ brew install mozilla-addon-sdk
==> Downloading http://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/addon-sdk-1.17.zip
######################################################################## 100.0%
🍺  /usr/local/Cellar/mozilla-addon-sdk/1.17: 850 files, 5.7M, built in 2 seconds

$ which cfx
/usr/local/bin/cfx

cfxコマンドも通る

$ cfx
Usage: cfx [options] command [command-specific options]

Supported Commands:
  init       - create a sample addon in an empty directory
  test       - run tests
  run        - run program
  xpi        - generate an xpi

Internal Commands:
  testcfx    - test the cfx tool
  testex     - test all example code
  testpkgs   - test all installed packages
  testall    - test whole environment

Experimental and internal commands and options are not supported and may be
changed or removed in the future.

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -v, --verbose         enable lots of output

  Supported Command-Specific Options:
    -b BINARY, --binary=BINARY
                        path to app binary (run, test, testall, testex,
                        testpkgs)
    --binary-args=CMDARGS
                        additional arguments passed to the binary (run, test)
    --dependencies      include tests for all deps (test, testall, testex,
                        testpkgs)
    --extra-packages=EXTRA_PACKAGES
                        extra packages to include, comma-separated. Default is
                        'addon-sdk'. (run, test, testall, testcfx, testex,
                        testpkgs, xpi)
    -f FILENAME[:TESTNAME], --filter=FILENAME[:TESTNAME]
                        only run tests whose filenames match FILENAME and
                        optionally match TESTNAME, both regexps (test,
                        testaddons, testall, testex, testpkgs)
    -g CONFIG, --use-config=CONFIG
                        use named config from local.json (run, test, testall,
                        testex, testpkgs, xpi)
    -p PROFILEDIR, --profiledir=PROFILEDIR
                        profile directory to pass to app (run, test, testall,
                        testex, testpkgs)
    --package-path=PACKAGEPATH
                        extra directories for package search (run, test, xpi)
    --parseable         display test output in a parseable format (run, test,
                        testaddons, testall, testex, testpkgs)
    --pkgdir=PKGDIR     package dir containing package.json; default is
                        current directory (run, test, xpi)
    --static-args=STATIC_ARGS
                        extra harness options as JSON (run, xpi)
    --templatedir=TEMPLATEDIR
                        XULRunner app/ext. template (run, xpi)
    --times=ITERATIONS  number of times to run tests (test, testall, testex,
                        testpkgs)
    --update-link=UPDATE_LINK
                        generate update.rdf (xpi)
    --update-url=UPDATE_URL
                        update URL in install.rdf (xpi)

  Experimental Command-Specific Options:
    -a APP, --app=APP   app to run: firefox (default), fennec, fennec-on-
                        device, xulrunner or thunderbird (run, test, testall,
                        testex, testpkgs)
    --abort-on-missing-module
                        Abort if required module is missing (run, test,
                        testpkgs, xpi)
    --check-memory      attempts to detect leaked compartments after a test
                        run (test, testaddons, testall, testpkgs)
    --force-mobile      Force compatibility with Firefox Mobile (run, test,
                        testall, xpi)
    --force-use-bundled-sdk
                        When --strip-sdk isn't passed, force using sdk modules
                        shipped in the xpi instead of firefox ones (run, test,
                        testall, testex, testpkgs, xpi)
    --harness-option=KEY=VALUE
                        Extra properties added to harness-options.json (xpi)
    --manifest-overload=MANIFEST_OVERLOAD
                        JSON file to overload package.json properties (xpi)
    --mobile-app=MOBILE_APP_NAME
                        Name of your Android application to use. Possible
                        values: 'firefox', 'firefox_beta', 'fennec_aurora',
                        'fennec' (for nightly). (run, test, testall)
    --no-run            Instead of launching the application, just show the
                        command for doing so.  Use this to launch the
                        application in a debugger like gdb. (run, test)
    --no-strip-xpi      retain unused modules in XPI (xpi)
    -o, --overload-modules
                        Overload JS modules integrated into Firefox with the
                        one from your SDK repository (run, test, testall,
                        testex, testpkgs)
    --output-file=OUTPUT_FILE
                        Where to put the finished .xpi (xpi)
    --stop-on-error     Stop running tests after the first failure (test,
                        testex, testpkgs)
    --strip-sdk         Do not ship SDK modules in the xpi (run, test,
                        testall, testex, testpkgs, xpi)

  Internal Command-Specific Options:
    --addons=ADDONS     paths of addons to install, comma-separated (run,
                        test, testall, testex, testpkgs)
    --e10s              enable out-of-process Jetpacks (run, test, testex,
                        testpkgs)
    --keydir=KEYDIR     obsolete, ignored (run, test, testall, testex,
                        testpkgs, xpi)
    --logfile=LOGFILE   log console output to file (run, test, testex,
                        testpkgs)
    --profile-memory=PROFILEMEMORY
                        profile memory usage (default is false) (test,
                        testall, testex, testpkgs)
    --test-runner-pkg=TEST_RUNNER_PKG
                        name of package containing test runner program
                        (default is test-harness) (test, testall, testex,
                        testpkgs)

実際に使ってみる

このページに従って。 developer.mozilla.org

まず、init処理をして、空のアドオンを作成する。

$ mkdir -p ~/mozilla/test_addon
$ cd ~/mozilla/test_addon/

$ cfx init
* lib directory created
* data directory created
* test directory created
* generated jID automatically: jid1-EjwLVj320kcArw
* package.json written
* test/test-main.js written
* lib/main.js written

Your sample add-on is now ready.
Do "cfx test" to test it and "cfx run" to try it.  Have fun!

IDが勝手に振られ、各ディレクトリと、package.json、main.jsというファイルが作成される。

package.sonの中身は以下。main.jsは空。

$ cat package.json 
{
  "name": "test_addon",
  "title": "test_addon",
  "id": "jid1-EjwLVj320kcArw",
  "description": "a basic add-on",
  "author": "",
  "license": "MPL 2.0",
  "version": "0.1"
}

チュートリアルにあるように、main.jsを編集する。

$ cat lib/main.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/");
}

拡張機能を動かす。

$ cfx run
Using binary at '/Applications/Firefox.app/Contents/MacOS/firefox-bin'.
Using profile at '/var/folders/93/2b32qdqn3v76tj1cnf6tmryc0000gn/T/tmperOXNA.mozrunner'.

Firefoxが起動して、右上にMozillaのアイコンが作成された。

f:id:mota5:20150420101605p:plain

ということで無事開発環境が整った。

拡張機能の自動更新

チュートリアルに乗っている通り、毎回cfx runを叩く手間を省くため、自動更新の方法も実施してみた。

そのコマンドの中でwgetを使っているのでMacにインストールする。(Macには標準でないのね・・・)

wgetをインストール rudix.org

次に自動更新用の拡張機能をインストール addons.mozilla.org

この拡張機能により、8888ポートで拡張機能更新用の待ち受けが行われるようだ。

これで準備ができたので、以下を実行して、5秒ごとに拡張機能をパッケージングし、アップロードする。

while true ; do cfx xpi ; wget --post-file=test_addon.xpi http://localhost:8888/ ; sleep 5 ; done

wgetでpost処理できることを知らなかった。。。

ちなみに、以下のような実行結果が出力されるが全く問題ない。

Exporting extension to test_addon.xpi.
--2015-04-19 22:49:18--  http://localhost:8888/
localhost (localhost) をDNSに問いあわせています... 127.0.0.1, fe80::1, ::1
localhost (localhost)|127.0.0.1|:8888 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 500 No Content
2015-04-19 22:49:18 エラー 500: No Content。

cfx to jpm

いまcfxで作っても捨てられる技術だから意味ないじゃん、とも思ったが、全部が無駄になるということでもないようなので、cfxで作ってしまっていいと思う。

developer.mozilla.org

In most respects, add-ons created with cfx will work fine with jpm. However, there are a few differences you have to know about.