JavaScript でかんたん XUL アプリに挑戦

こんにちは!
みなさんガジェットつくってますか!
なんだか最近、色々な種類があるみたいですね!

(以下略!)

そしたら意外と簡単だった…!
これならぼくにも作れそう!!

ってことで、ちょっとメモしておきますね!

どれにしようかな…!

  • おもしろいこと
  • Ubuntu で動けばいいや*1
  • 自分とこで書きやすいのがいい

こんな感じで考えていくと…
最終的に XUL アプリケーション,ってことになりました!

XUL で作られたツールなら,いつも使っているよ!
Firefox とか Thunderbird とかね)
だから XUL アプリに決定!

つくるのむつかしそう?

XUL のアプリって C から libxul をゴリゴリ触らないとダメなんじゃないの?

なんて思っていた時期がぼくにもありました…!

大丈夫!XULRunner を使えば(HTML に似た)XULJavaScript だけでできるよ!

だからホームページ作るのと同じくらい簡単に感じる人もいるかもしれないですね!

ブラウザ上のページだと、JavaScriptとかで他のサイトの情報を取得できなかったり
ファイルの読み書きできなかったりと、色々な制約があるんだけど、
XULRunner なら XPCOM もあるから
そんな制約なしで、ウイルスでも何でも好きなものがバンバンつくれます!
やったね!

つくるための準備

準備は Ubuntu Linux 8.10 でのやりかたです!
Windows とか Mac とか一般的な OS 使ってる人はどうせニヤニヤしながら眺めているだけだろうから,ほんとにやりたい人は Getting started with XULRunner - Archive of obsolete content | MDN を参考に自分で適当にやっちゃってください!

Ubuntu だととくになにもしなくても*2 XULRunner が入っていたから省略するよ!)

ちゃんと設定できてるかな?

端末を開いて,xulrunner って入れてみよう!
なんかでてきたら XULRunner はインストールされてるよ!

よし!つくろう!

ぼくはいつも ~/tmp/ にガラクタファイルを溜め込んでいってるので,
~/tmp/myapp ってフォルダを作ってみました!
はい!今回つくるやつは「myapp」っていう XUL アプリです!

作業用フォルダに必要なフォルダを用意する

シンプルな XUL アプリの場合,だいたい下記のようなフォルダ&ファイル構成になるよ!

/myapp
  /chrome
    /content
      main.xul
    chrome.manifest
  /defaults
    /preferences
      prefs.js
  application.ini

だから,まずディレクトリをきっておこう!

% cd myapp

% mkdir -p chrome/content defaults/preferences

作業用フォルダに必要なファイルを用意する

4つのファイルを用意しよう!
ひとつが,XUL アプリの情報を設定する application.ini ファイル。
もうひとつが,使用するリソース(画像とか JavaScript ファイルとか)の場所のレイアウトを指定する chrome.manifest ファイル。
さらにもうひとつが,設定を書くための prefs.js ファイル*3
最後が,メインになる main.xul ファイル!

XUL アプリの情報を設定する application.ini ファイル

作業用フォルダの直下に新しく「application.ini」ってファイルを作ってね!

% vi application.ini

中身は…

[App]
Vendor=dayflower
Name=My App
Version=1.0
BuildID=20090119
ID=xulapp@example.org

[Gecko]
MinVersion=1.9
MaxVersion=1.9.0.*

これをコピペでok!
(ほんとは Vendor とか ID を適宜書き換えてほしいけど…)

リソースレイアウトを設定する chrome.manifest ファイル

作業用フォルダの chrome/ フォルダ以下に chrome.manifest ファイルを作ろう!

% vi chrome/chrome.manifest

中身は…

content myapp file:content/

たったこれだけ!これもコピペでok!

念のためにちょっと解説?すると,XUL アプリケーションや Firefox 拡張機能では,使用するファイル(画像とか CSS とか html とか xul とか js とか)を chrome/ フォルダ以下につっこむんだけど,一般的にはこの chrome/ フォルダ以下を JAR ファイル(ZIP 形式)で圧縮して配布することが多いんだ。だけど上記のように書くと,圧縮はしてなくて,chrome/content/ フォルダ以下にそのままおいてあるよ,という意味になるよ!

設定ファイル prefs.js ファイル

作業用フォルダの defaults/preferences/ フォルダ以下に prefs.js ファイルを作ろう!

% vi defaults/preferences/prefs.js

中身は…

pref("toolkit.defaultChromeURI", "chrome://myapp/content/main.xul");

pref("browser.dom.window.dump.enabled", true);

これもまたコピペでok!

念のために説明すると,上の行は XULRunner にメインウィンドウとして使われる XUL ファイルの名前を教えてあげるための設定だよ!「chrome://」という形式からもわかるように,これは chrome.manifest にさっき設定したマッピングと関連している。さきほど chromemyappcontentfile:content/((これは chrome/ フォルダからの相対パス指定だよ。)) って設定したので,chrome://myapp/content/main.xul という表記は,(chrome/)content/main.xul というファイルを指定していることになるんだ。ここはまあわかんなくてもok!

下の行は,のちほど dump() という関数でデバッグ用出力を可能にするための設定!そのた JavaScript コンソールにデバッグ情報を出力する方法もあるけど,その場合の設定は [https://developer.mozilla.org/ja/Debugging_a_XULRunner_Application:title] をみてね!

XUL ファイル

いよいよ chrome/content/main.xul ファイルを作る番だね!

% vi chrome/content/main.xul

中身は…

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>

<window id="main" title="Konnichiha Konnichiha" width="400" height="300"
 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <script>
<![CDATA[
function start() {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 200) {
            view(xhr);
        }
    };

    xhr.open('get', 'http://b.hatena.ne.jp/hotentry');
    xhr.send(null);
}

function view(xhr) {
    dump(xhr.getAllResponseHeaders());
    document.getElementById('message').value = xhr.responseText;
}
]]>
  </script>
  <textbox id="message" multiline="true" rows="10" readonly="true"
           value="こんにちはこんにちは!"/>
  <button id="pushme" label="ひみつボタン" oncommand="start()"/>
</window>

これもコピペでオッケー!
ただし,文字コードは UTF-8 で保存してね!

これは textbox の id をかえたくらいで,ほとんどはまちちゃんのコードのコピペだよ。JavaScript + DOM ってすばらしいね!

実行しよう!

端末を起動して,作業フォルダに移動…

% cd ~/tmp/myapp

さっきつくったやつを実行…!

% xulrunner application.ini

できた!やった!なんかうごいた!
ひみつボタンを押したら,はてなブックマークのソースコードが表示されたよー。

改造しよう!

XUL ファイルとか JavaScript は,Mozilla Firefox と同じやつが使われてるらしいですよ!

てことは,普段ホームページ作りの時に「あぁこれ IE だと使えないからなぁ」
なんて諦めていたやつが色々つかえるかもしれないですね!
XPath とか Canvas とか,なんかそういうの!

あと prototype.js とか jQuery みたいな便利ライブラリも普通に使えるよ!(たぶん)
やった!すごい!べんり!

だけど XUL アプリケーションのちょっとまずいところ

  • HTML のかわりに XUL とかいう謎なファイルを書かなくちゃいけない

謎なファイルって書いたけど,みんなも HTML を勉強するとき色々覚えたよね?
<input type="checkbox"> って書くとチェックボックスをだせるとか。
XUL の場合,その代わりにたとえば <checkbox> と書けばいいんだ。
つまり,新しいタグが増えたと思えばいいんだよ!
それに <colorpicker> とか素敵なウィジェットも揃っているよ!

くわしくは XUL controls - Mozilla | MDN をみてね!

  • アプリケーションの配布がたいへん

今回の Ubuntu Linux の場合,たいていは xulrunner はもともとインストールされている。
けど,Windows とかの場合は,ユーザに XULRunner をダウンロード*4させなきゃいけない。
(まぁ Windows の場合解凍するだけで大丈夫らしいし,Mac OS X の場合はインストーラ形式になってるよ)

2009-01-20 追記:

teramako
id:teramako XUL, xulrunner ネタを取られた...orz // 悔しいので一つネタを。xulrunnerじゃなくてもFx3からは firefox -app application.ini で起動できたりするよ

http://b.hatena.ne.jp/teramako/20090119#bookmark-11728256

ごめんなさいごめんなさい!
それはともかく有益な情報をありがとう!
Firefox 3 だと,わざわざ xulrunner をインストールしなくても,
Firefox のバイナリから XUL アプリケーションを動かせるんだね。
これでアプリケーション配布の間口がちょっと広くなるね!

2009-01-20 追記おわり

AIR でもランタイムをインストールさせる必要はあるけど,
アプリケーションの配布と同時にインストールも行うようにできるよ。
そもそも AIR の場合,アプリケーションの標準的な配布方法が定まっているのが大きいね!

参考になるページ

公式のページに参考になることが色々書いてあるよ!

みんな作って、どんどこ公開しちゃえばいいんじゃないかな!
(できれば、ぼくが見て勉強できるようにソースコード付きで…!)

おわりに

いわずとしれてるけど,これは下記のすばらしい記事へのオマージュだよ!

あとは私感だよ!

  • main.xul ファイルに JavaScript とかボタンのラベルとかゴリゴリ書いたけど,これは行儀がよくないよ!
    • スクリプトは分離しよう!
    • ウィジェットのラベルなどは実体参照形式((HTML でいうところの &amp; みたいな書き方のことだよ!XUL だとこの DTD を自分で用意することで,自分オリジナルな実体宣言ができるんだ。あとは,その参照先は英語の場合「foobar」だよ,みたいに DTD に書けば,世界中のみんなから使ってもらえるアプリケーションになるよ!))で書くと国際化もできるようになるよ!
  • Firefox 拡張機能の書き方を勉強するより,XULRunner から書きはじめるほうが手軽な気がしたよ!
    • (拡張機能書いたことないけどね)
  • 「Firefox が動くところでは XUL アプリケーションが動く」,というのはなかなか Run Anywhere でいい感じだよ!
    • AIR の場合,たとえ Flash が動く環境でも Adobe が AIR ランタイムを移植してくれないと動かないよね。
  • はまちちゃんの書き方は真似しようと思ってもなかなか難しいよ!

*1:原典をみればわかるけど,Windows や Mac OS X で動かすのも,たいして難しくはないよ!

*2:Firefox 3 が入っていれば,だけど

*3:これはいかにも必須じゃなさそうだけど,XULRunner にメインウィンドウとなる XUL ファイルの名前をわたすために使います。

*4:http://releases.mozilla.org/pub/mozilla.org/xulrunner/releases/1.9.0.5/runtimes/ とかにあるよ。