第 2 回 Firefox 出張ワークショップ発表資料2009年07月15日 02時17分

先日京都コンピュータ学院で開催されたオープンソースカンファレンス 2009 Kansai、その中の一セッション「第 2 回 Firefox 出張ワークショップ ~基礎から学べる拡張機能開発~」に講師として参加させていただきました。私の担当した後半、実際に拡張機能を作ってみる部分の資料及び完成版の拡張は以下になります。

「わからないことがあったとき、どうやって調べるか」をひとつの柱として話を進めていきたかったのですが、つたない進行で後半ややペースが押し気味になってしまい、終了時間を 5 分ほど過ぎて最低限動くものが完成するという有様でした。人によっては休憩時間もろくに取れない状態になってしまい申し訳ありません。

以下に質問のあった点、補足等を記します。

「進む」メニューの特定

DOM Inspector でコンテキストメニューの「進む」メニューを探すのにいちいち文書ツリーをたどっていったのですが、後ほどあさんから指摘があったように、クリックで要素を選択する機能を使ったほうがはるかに簡単でした。

具体的には、DOM Inspector でブラウザウィンドウを選択後、マウス選択ボタンをクリックし、ブラウザウィンドウに戻ったらアプリケーションキーまたは Shift + F10 キーでコンテキストメニューを表示させます。そうすれば後は「進む」メニューを直接クリックするだけで DOM Inspector 側で適切な要素が選択されます。

[図: DOM Inspector のマウス選択ボタン] [図: キー操作で表示したコンテキストメニュー]

マウス選択状態では右クリック (Mac では Ctrl + クリック) してもその要素が選択されてしまうので、文書ツリーをたどっていく必要があると思っていたのですが、キー操作でコンテキストメニューを表示させればいいというのは個人的に盲点でした。

名前付き関数式

ContextHistory オブジェクトの各メソッドを記述する際、

var ContextHistory = {
  init: function CH_init() { ... },
};

CH_init のような名前をつけていることへの質問がありました。名前をつけることでスタックトレースにその名前が出るようになり、デバッグが楽になります。つけないと anonymous function といった表示になり、名前から関数を特定できません。

XUL 要素の動的な生成

XUL、XHTML、SVG といった特定のXML応用の要素を生成するときは、document.createElementNS メソッドを使い、第 1 引数にその XML 応用の名前空間 URI を指定します。一応 XUL 文書中では createElement メソッドでも XUL 要素が生成されますが、そのような DOM 仕様にない Mozilla 独自の振る舞いに依存すべきではありません。さもなくば XUL と他の XML 応用とを組み合わせるときなどに混乱を招くことになります。

よく参照する Firefox のソースコード

Mozilla Cross-Reference で Mozilla の (Firefox の) ソースコードを閲覧・検索できます。私の場合、実際によく参照するのは次のような箇所です。

Firefox の機能とそのソースコードの場所
機能 Firefox 3.5 系統 最新開発版
ブラウザの UI /browser/base/content/ /browser/base/content/
DOM インターフェース /dom/public/idl/ /dom/interfaces/
UI 部品 /toolkit/content/widgets/ /toolkit/content/widgets/

数値への変換

JavaScript で +exprNumber(expr) と同じ意味であり、expr を数値へ変換した結果を返します。

ラベルの国際化

追加したメニューのラベルを、ロケールによらずツールバーの履歴ドロップダウンボタンのツールチップと同じにするのが目標でした。たとえば次のような手順が考えられます。

  1. DOM Inspector で履歴ドロップダウンボタンを選択し、その id を確認する。
  2. view-source:chrome://browser/content/browser.xul からその id を検索し、ツールチップ文字列を表す実体参照を見つける。
  3. MXR で実体名を検索し、その実体が含まれる DTD ファイルを見つける。
  4. MXR で見つかった DTD ファイル名と browser.xul のソースで参照している DTD の chrome URI とを見比べ、その DTD ファイルを指す chrome URI の見当をつける。
  5. オーバーレイファイルからその DTD を参照し、メニューのラベルとしてその実体参照を記述する。

[図: DOM Inspector で選択した履歴ドロップダウンボタン] [図: 履歴ドロップダウンボタンのソースコード] [図: MXR での実体名の検索結果] [図: browser.xul が参照する DTD]

<!DOCTYPE overlay [
  <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
  %browserDTD;
]>

修正の反映

最初のほうで QuickRestart を紹介した影響か、ソースコードを修正するたびに Firefox を再起動していた人が多かったですが、実は about:config から nglayout.debug.disable_xul_cache を true にしておけば、新しいウィンドウを開くたびに最新のソースコードが読み込みなおされます。ただし、XPCOM コンポーネントJavaScript モジュールはこの限りではありません。

拡張の JavaScript の名前空間

JavaScript には名前空間が存在しないので、拡張のスクリプトを書くときは、Firefox 本体や別の拡張が使っている名前と競合しないように注意する必要があります。これは拡張から Firefox 本体を自由に操作できることの裏返しでもあります。

JAR ファイルの利点

拡張の構成ファイルを単独の JAR ファイルに固めることで、アクセスするファイルがひとつですむようになり、ファイルアクセスの負荷を減らすことができるそうです。

ローカルな拡張の自動更新

たとえば企業内のみで使いたい拡張があるというとき、自動更新に対応させるためには、SSL を通じて更新を配布するか、電子署名を使い拡張に公開鍵を含める必要があるそうです。