このサイトの記事更新は2019年11月に終了されました。過去記事アーカイブを公開しています。

投稿されたすべてのトピック

拡張機能デバッグインターフェイス

拡張機能開発時によく使うログや表明 (assertion) などのためのインターフェイスのサンプルコードです

var myextension = {
	// debug interface
	debug: {
		// https://developer.mozilla.org/en/NsIConsoleService
		_consoleservice: Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService),
		_Cc_scripterror: Components.classes["@mozilla.org/scripterror;1"],
		_Ci_scripterror: Components.interfaces.nsIScriptError,
		enabled: false, // set true to output
		noFirebug: false, // don't show object in Firebug
		prefix: "",  // prefix string
		createScripterror: function() this._Cc_scripterror.createInstance(this._Ci_scripterror),
		// log for Firebug with existence check
		logFirebug: function(x) this.enabled && !this.noFirebug && Firebug && Firebug.Console && Firebug.Console.log(x),
		logFirebugOnlyObject: function(x) typeof x == "object" && x != null && this.logFirebug(x),
		// log/warn/error in console
		log: function(message) {
			if (this.enabled) {
				this._consoleservice.logStringMessage(this.prefix+message);
				this.logFirebugOnlyObject(message);
			}
		},
		warn: function(message) {
			if (this.enabled) {
				var stack = Components.stack.caller;
				var error = this._Cc_scripterror.createInstance(this._Ci_scripterror);
				error.init(this.prefix+message, stack.filename, null, stack.lineNumber, null, this._Ci_scripterror.warningFlag, null);
				this._consoleservice.logMessage(error);
				this.logFirebugOnlyObject(message);
			}
		},
		error: function(message) {
			if (this.enabled) {
				var stack = Components.stack.caller;
				var error = this._Cc_scripterror.createInstance(this._Ci_scripterror);
				error.init(this.prefix+message, stack.filename, null, stack.lineNumber, null, this._Ci_scripterror.errorFlag, null);
				this._consoleservice.logMessage(error);
				this.logFirebugOnlyObject(message);
			}
		},
		// debug with exception (error objects)
		exception: function(error) {
			if (this.enabled) {
				Components.utils.reportError(error);
				this.logFirebugOnlyObject(error);
			}
		},
		stack: function(error) {
			if (this.enabled) {
				if (error instanceof Error) {
					this._consoleservice.logStringMessage(this.prefix+error.stack);
				}
				else {
					error = new Error();
					var callerstack = error.stack.replace(/^.*\n.*\n/, "");
					this._consoleservice.logStringMessage(this.prefix+callerstack);
				}
				this.logFirebugOnlyObject(error);
			}
		},
		// alert and assert
		alert: function(message) {
			if (this.enabled) {
				window.alert(this.prefix + message);
				this.logFirebugOnlyObject(message);
			}
		},
		assert: function(cond, message) {
			var failed = this.enabled && !cond;
			if (failed) {
				var message = this.prefix+message;
				var stack = Components.stack.caller;
				var error = this._Cc_scripterror.createInstance(this._Ci_scripterror);
				error.init(message, stack.filename, null, stack.lineNumber, null, this._Ci_scripterror.errorFlag, null);
				this._consoleservice.logMessage(error);
				window.alert(message);
				this.logFirebugOnlyObject(message);
			}
			return !failed;
		}
	},
	onLoad: function() {
		this.debug.enabled = true;
		this.debug.prefix = "myextension debug:\n";
		this.debug.log("myextension inited!");
	}
}
window.addEventListener("load", function() { myextension.onLoad() }, false);

debug オブジェクトを自分の拡張機能専用オブジェクトのプロパティとして定義し、debug.log() などのメソッドを使います。debug.prefix に文字列を設定しておけば、コンソールのメッセージすべての先頭にその文字列が表示されるので検索しやすくなります。引数がオブジェクトの場合、Firebug がインストールされていれば Firebug のコンソールにも出力します。

上記の例では直接 true を代入していますが、debug.enabled プロパティはユーザ設定から読み込むようにすれば、開発環境だけでログを出力するといった使い方もできます。

より詳しい解説の追加などはまた後日…

CSS によるブラウザ履歴の漏えいを防ぐ取り組み

これは、Mozilla Security Blog の記事 Plugging the CSS History Leak (英文) の抄訳です。Web 開発者の方は Mozilla Hacks の記事抄訳 CSS の :visited に行われるプライバシー対策 も参照してください。

プライバシーの保護は必ずしも簡単なことではありません

Mozilla では近く、以前からブラウザ各社が取り組んでいる個人情報漏えい問題の対策を Firefox の開発ツリーに追加します。私たちはこの改善を非常に楽しみにしており、他のブラウザも後に続いてくれることを期待しています。しかし、これは解決が難しい問題であるため、Mozilla がなぜこのようなアプローチを取ることにしたのか説明しておきたいと思います。

履歴の取得

Web ページ上のリンクは、ユーザがそのリンク先を訪れたことがあるかどうかによって見た目が変わる場合があります。既にご存知かもしれませんが、通常、訪問済みリンクは青色から紫色に変わります。これは、Web デザイナーが優れた Web サイトを作成できるよう用意されている多くの機能のひとつに過ぎず、たいていの場合は良心的に利用されています。

問題は、リンクを表示しているページがその見た目を判別でき、ユーザがどのリンク先を訪れたことがあるかを知る手がかりとなってしまうということです。つまり、ユーザだけでなく Web サイトも、ユーザの Web サイト閲覧履歴を知ることができてしまうのです。

元々 Web の便利な機能のひとつとして定義された訪問済みリンクのスタイル付けは、長いこと Web の一部として利用されてきました。つまりこれは非常に古い問題で、これまでも時折論争を巻き起こしています。

最も単純な修正を行うとすれば、未訪問リンクと訪問済みリンクのスタイルの違いをなくしてしまうことですが、これでは利便性が損なわれます。Web サイトだけでなくユーザ自身も、どのリンク先を訪れたことがあるか分からなくなってしまいます。そこで Mozilla では、開発者の David Baron が Web サイトへの影響を最小限に抑えつつユーザのプライバシーを守る方法 を考案し、ユーザ保護の観点から Firefox に組み込むことにしました。私たちはこれがこの問題に対する最善の解決策であると考えており、他のブラウザも同様の取り組みを行ってもらえれば嬉しく思います。

技術的な詳細

ここでの最大の脅威は、高い処理能力を備えた技術、つまりユーザのブラウザからすばやく大量の情報を抜き出すプログラムです。そうした技術は、非常に集中した攻撃だけでなく、一般的に、様々な攻撃者にとってより有効な、広範な「総当たり攻撃」を可能にすることから、特に憂慮すべきです。(潜在的にはフィンガープリントの採取も含まれます)

JavaScript の getComputedStyle() 関数とそれに関連した機能は高速であり、1 分間に何十万件ものリンクを訪問済みかどうか推測するのに利用できます。Web の仕組みに大幅な変更を加えることなく、ユーザの訪問済みリンクを Web サイトから取得されないようにするため、以下のような 3 つの極めて巧妙な方法でリンクのスタイル付けを行うアプローチを取ることにしました。

変更点 1: レイアウトに基づいた攻撃

まず、訪問済みリンクを未訪問リンクと区別するのに使用できるスタイルの種類を制限します。具体的には、訪問済みリンクは、文字、背景、アウトライン、ボーダー、SVG の線と塗りといった、配色のみ変えられるようにします。その他のスタイルの変更はいずれも、背景画像を読み込んだりページ上のスタイル付けされたコンテンツの位置やサイズを変えたりすることで、リンクが訪問済みかどうかを分かるようにするものですが、これらは訪問済みリンクを判別し特定するのに利用されるおそれがあります。

私たちが変更できることはカスケーディングスタイルシート (CSS) の許容範囲になりますが、CSS 2.1 の仕様書は訪問済みリンクの悪用を考慮しています。

「そのため、ユーザエージェントはすべてのリンクを未訪問リンクとして扱うか、訪問済みと未訪問リンクを異なるように表示しつつ、ユーザのプライバシーを守るその他の方法を実装することができます。」(CSS 2 仕様書 より引用)

変更点 2: 一部のタイミング攻撃

次に、Gecko レンダリングエンジンの実装にいくつかの変更を加え、訪問済みと未訪問リンクの表示にかかる時間の違いを最小限にするため、処理プロセスを均一化します。この変更により、訪問済みと未訪問リンクの両方について、すべてのスタイルがすべてのリンク上で制御され、保存されるようになります。その結果、リンクがスタイル付けされるときに、適切なスタイルが選ばれ、訪問済みと未訪問リンクのコードパスが原則として同じ長さとなります。これによって、一部の展開が容易なタイミング攻撃を排除できます。

変更点 3: 算出スタイルを利用した攻撃

JavaScript による、実際に適用されているスタイルの取得が制限されます。Web ページがリンク (とその子孫要素) の算出スタイルを取得しようとすると、Firefox は未訪問リンクのスタイル定義を返すようになります。

これがユーザにとってどのような意味を持つか

ほとんどのユーザは、Web サイトの表示が変わったことには気付かないでしょう。ごく一部の Web サイトでは、見た目が少し変わる可能性もありますが、訪問済みリンクはこれまで通り異なる色で表示されます。また、配色以外のスタイルで訪問済みリンクを区別している一部のサイトでは、上記の変更に対応するまで、当初は若干見た目が崩れる可能性もありますが、それはユーザのプライバシーを守るために正しいトレードオフであると私たちは考えます。これは、厄介で非常に作り込まれた攻撃手法なのです。私たちは Web のいかなる部分も壊したくありませんが、可能な限り攻撃を阻止する必要があります。

もっとも、私たちは現実に目を向けなければなりません。すべてのブラウザは、個人情報の漏えい原因となる様々な機能を実装しており、CSS による履歴の取得を制限しても、これらの漏えいをすべて防げるわけではありません。しかし、どのような方法を使っても、この最も恐ろしく最も効果的な履歴の取得を阻止することは、ユーザのプライバシー保護に大きなメリットをもたらすことから、重要なことであると私たちは信じています。

他の攻撃が心配であったり、この問題の修正版が手に入るのを待てないときは、バージョン 3.5 以降の Firefox に実装済みの、訪問済みリンクのスタイル付けを完全に無効にする (この手の攻撃を今すぐ阻止する) 方法をお試しください。設定エディタ about:config を開いて、layout.css.visited_links_enabled の設定値を false に変更すれば完了です。これにより履歴の漏えいを防ぐことはできますが、どの Web サイトでも訪問済みリンクを見分けられなくなることに注意してください。

Web 上でのプライバシーを高めるために

私たちは、ユーザのプライバシー保護に対する期待と、Web 上で実際に起きていることのギャップを埋めたいと考えています。ブラウザが確実にプライバシーを守ってくれると期待するユーザもいるので、可能であればそれに応えたいと思います。しかしながら、プライバシー保護というものは、ブラウザに単純に追加できる機能ではありません。時には利便性を犠牲にすることもあるでしょう。私たちは、ユーザにより安全な Web 体験を提供しつつ、Web デザイナーにとって柔軟性のバランスを取れる修正方法を見つけたと考えています。

Firefox 3.7 でのナビゲーションツールバーのアイコン画像サイズ

注意:このトピックは Firefox 3.7 での仕様変更について触れています。また、 Windows 版のデフォルトテーマを前提としており、他のOSについては未確認です。他のOSについての情報求みます。

Firefox 3.7 では、ナビゲーションツールバーに配置するボタン(戻る・進む・更新・ホームなど)のアイコン画像サイズが下表のように変わるようです。なお、下表の「小さいアイコン」とは、「ツールバーのカスタマイズ」で「小さいアイコンを使用」オプションを有効にしている場合、あるいはブックマークツールバー上にボタンを配置した場合のアイコンを意味します。

Firefox 3.6 Firefox 3.7
通常アイコン 24×24ピクセル 18×18ピクセル
小さいアイコン 16×16ピクセル 18×18ピクセル

拡張機能にてナビゲーションツールバーにボタンを追加している場合、この仕様変更の影響を受けるようです。ここでは、例として、拡張機能にて下記のような XUL オーバーレイによってナビゲーションツールバーにボタンを追加するとします。

<toolbarpalette id="BrowserToolbarPalette">
  <toolbarbutton id="myaddon-button"
                   class="toolbarbutton-1 chromeclass-toolbar-additional"
                   label="My Addon" />
</toolbarpalette>

Firefox 3.6 までは、一般的には以下のようなスタイルシートによって通常アイコンと小さいアイコンのスタイルを別々に定義します(参考)。なお、「largeicon.png」は24×24ピクセルの画像、「smallicon.png」は16×16ピクセルの画像とします。

/* 通常アイコン */
#myaddon-button {
	list-style-image: url("chrome://myaddon/skin/largeicon.png");
}

/* 小さいアイコン */
toolbar[iconsize="small"] #myaddon-button {
	list-style-image: url("chrome://myaddon/skin/smallicon.png");
}

このとき、 Firefox 3.6 では通常アイコン・小さいアイコンともに本来の画像サイズできれいに表示されますが、 Firefox 3.7 では通常アイコンは「largeicon.png」を本来のサイズである24×24ピクセルから18×18ピクセルへと縮小され、小さいアイコンは「smallicon.png」を本来のサイズである16×16ピクセルを18×18ピクセルへ拡大されます。下表のように、小さいアイコンの表示がきれいでなくなる傾向があります。

Firefox 3.6 Firefox 3.7
通常アイコン
小さいアイコン

Firefox 3.7 でも本来の画像サイズでアイコンをきれいに表示したい場合、いくつかの方法があるかと思いますが、ここでは Firefox 3.7 以上専用のスタイルシートを別途追加する方式を解説します。

Firefox が特定のバージョンの場合に限り、指定した XUL に対してスタイルシートを適用したい場合、以下のようにクロムマニフェストの「style」命令へ「appversion」フラグをセットします。なお、ツールバーボタン用のスタイルシートは、「browser.xul」(ブラウザウィンドウ)と「customizeToolbar.xul」(ツールバーのカスタマイズウィンドウ)の両方に適用させます。

# apply stylesheet if Firefox 3.7a or later
style  chrome://browser/content/browser.xul  chrome://myaddon/skin/fx37.css  appversion>=3.7a
style  chrome://global/content/customizeToolbar.xul  chrome://myaddon/skin/fx37.css  appversion>=3.7a

拡張機能の skin パッケージに含めるFirefox 3.7 以上専用のスタイルシート「fx37.css」 には以下のような内容を記述します。 xul:toolbarbutton 要素自体に画像を設定するのではなく、内部の匿名 xul:image 要素に対して画像およびサイズを設定します。

/* 通常アイコン・小さいアイコン共通 */
#myaddon-button > .toolbarbutton-icon {
	list-style-image: url("chrome://myaddon/skin/smallicon.png");
	width: 16px;
	height: 16px;
}

これにより、以下のように通常アイコン・小さいアイコンともに「smallicon.png」が本来の16×16ピクセルできれいに表示されます。

Firefox 3.7
通常アイコン
小さいアイコン

Firefox 標準のツールバーボタンと同じ18×18ピクセルの画像を Firefox 3.7 以降用のアイコン画像として別途作成し、上記「fx37.css」にて適用するのもよいかもしれません。

Windowsのマウスドライバもしくはユーティリティ開発者への参考情報

MozillaWikiにWindowsのマウスのドライバやユーティリティ開発者向けの参考情報のドキュメントを投稿しました。これの和訳をこちらに書いておきます。英語版が常に最新版となりますので、実際の開発時には原文の方を参照してください。

Gecko:Notes for mouse driver developers on Windows

このドキュメントは参考情報です。

WM_MOUSEWHEELWM_MOUSEHWHEELを送信してください

GeckoはWM_MOUSEWHEELWM_MOUSEHWHEELの両方をサポートしています。全てのマウスドライバ、ユーティリティはGeckoのウインドウに対してはこれらのメッセージを送信すべきです。

Gecko 1.9.3以降(Firefox 3.7以降)はWM_VSCROLLWM_HSCROLLメッセージもサポートされますが、マウスドライバ、ユーティリティはこれらのメッセージをマウスホイールの操作時に利用してはいけません。Geckoはこれらのメッセージと、WM_MOUSEWHEEL/WM_MOUSEHWHEELは異なる意味をもつメッセージだと考え、異なる処理をしているからです。具体的には、WM_MOUSEWHEELWM_MOUSEHWHEELDOMMouseScrollイベントをWebページ上で生成します。つまり、Webアプリケーションの作者はマウスホイールの回転イベントとして、これをハンドリングすることができ、また、コンテンツのスクロールを抑制することもできます。これに対して、WM_VSCROLLWM_HSCROLLはこのDOMイベントを生成せずに、単にスクロール可能な領域をスクロールするのみです。つまり、Webアプリケーションの作者にはスクロールバーの操作と見分けがつきません。

フォーカスをもつGeckoのウインドウにメッセージを送信してください

カーソルの下にあるウインドウではなく、フォーカスを持ったGeckoのウインドウに対してメッセージを送信してください。Geckoはスクロール対象を決定するときにマウスカーソルの位置を利用します(詳しいルールはGecko:Mouse_Wheel_Scrollingを参照してください)。Geckoはカーソルの下にあるウインドウに対して自動的にメッセージを再送信します。

Geckoはプラグインのウインドウがカーソルの下にあっても、これに対してメッセージを直接再送信しません。その理由はGeckoはマウスホイールの操作にはトランザクションが成立していると考えているからです(詳細はGecko:Mouse_Wheel_Scrolling)。ユーザはプラグインの親のスクロール可能な領域をスクロールしたいのかもしれません。たとえば、プラグインウインドウが親のスクロールによってカーソルの下へ移動してきた時、Geckoはその直後のホイールイベントも親をスクロールし続けるように処理します。もし、マウスドライバやユーティリティがメッセージを直接プラグインのウインドウに送信した場合、この処理ができなくなってしまいます。

マウスホイールのメッセージを不明なウインドウに対して利用してください

Gecko 1.9.2以降(Firefox 3.6以降)は、次のクラス名を持つウインドウを生成します。これらは将来のバージョンで変更される可能性があることに注意してください。

  • MozillaHiddenWindowClass
  • MozillaUIWindowClass
  • MozillaContentWindowClass
  • MozillaContentFrameWindowClass
  • MozillaWindowClass
  • MozillaDialogClass
  • MozillaDropShadowWindowClass

フォーカスをもったウインドウがこれらのクラス名であった場合、WM_MOUSEWHEELWM_MOUSEHWHEELを細工なく送信できると考えて問題ありません。

Firefox 3.6ではGeckoのウインドウの構造が変更になりました。この時、私たちはいくつかのマウスドライバ、ユーティリティがこれらのメッセージを送信してこなくなったことを確認しています。これらのメッセージはWindowsアプリケーションにとってマウスホイールのアクションを意味する標準のイベントです。歴史的な問題から、古いアプリケーションや一部のアプリケーションがこれらのイベントを期待通りに処理してくれないことはあるでしょう。マウスドライバやユーティリティはそういったアプリケーションのウインドウに対しては小細工を行うべきかもしれません。ですが、もしあなたが把握していないウインドウ全てがそういったアプリケーションのウインドウであると決めつけているのであればそれは良くないことです。

拡張アンインストール時になんらかの処理を行う

 古くから拡張を作られている方で拡張アンインストール時になんらかの処理を行うために、ObserverService の通知を利用されている方も少なくないかと思います。またあるいは FUEL を利用して簡便に拡張のアンインストールを検出している方も少なくないと思います。
 これらの2つの方法が使えなくなる予定になっています。最新の方法ではアドオンマネージャを使って、拡張の削除を検出するようになっています。

 拙作 Hütte Nippon では、ほぼサンプル通り以下のようなコードになっています。

(function(){
  let Cc=Components.classes;
  let Ci=Components.interfaces;
  let tm;
  function rmStringValue(pentry){
    try {
      Cc["@mozilla.org/preferences-service;1"]
        .getService(Ci.nsIPrefBranch).deleteBranch(pentry);
    }catch(e){
      return false;
    }
    return true;
  };
  function clearProfile(){
    rmStringValue('extensions.weather.prefecture');
    rmStringValue('extensions.weather.region');
    rmStringValue('extensions.weather@avidya.ne.jp.install-event-fired');
  };
  function init(){
    window.clearTimeout(tm);

    let listener = {
      onUninstalling: function(addon) {
        if (addon.id == "weather@avidya.ne.jp") {
          clearProfile();
        }
      },
      onOperationCancelled: function(addon) {
        if (addon.id == "weather@avidya.ne.jp") {
          beingUninstalled = (addon.pendingOperations & AddonManager.PENDING_UNINSTALL) != 0;
        }
      }
    }

    Components.utils.import("resource://gre/modules/AddonManager.jsm");
    AddonManager.addAddonListener(listener);
  }
  tm=window.setTimeout(init,500);
})();

 なお、Hütte Nippon のライセンスを以前から MIT License に変更しています。コピーして使うなり、参考にするなり自由にご利用ください。
 また Hütte Nippon の全ソースコードは github にて公開しています。

FUEL の仕様変更予定 (Application.getExtensions)

Firefox の拡張機能を簡単に書けるようにするためのライブラリ FUEL には拡張機能の情報を取得するメソッドが存在しますが、今度 Jetpack 対応なども含めて Extension Manager 周りが大きく書き直されるのに伴い、一点だけ仕様変更が予定されています。

拡張機能の情報を得る処理はこれまで同期処理となっていましたが、Firefox 高速化のためなどに様々な処理が非同期化されているのと同じく、Extension Manager 周りのコードが非同期処理に変更されます。この影響により、FUEL のメソッド 1 つだけが変更されることになります。

例えば以下のように Application.extensions.get() メソッドを用いたコードは変更が必要になります:

alert(Application.extensions.get("my-addon@foo.com").version);

このようなコードであれば次のように Application.getExtensions() メソッドに callback 関数を渡す形に書き換えることになります:

Application.getExtensions(function(extensions) {
  alert(extensions.get("my-addon@foo.com").version);
});

詳しくは Dave さんのブログを参照してください:

http://www.oxymoronical.com/blog/2010/03/How-were-breaking-some-extensions-in-the-near-future

nsIPrefはFirefox 3.7以降では利用できません

加藤です。

現在のFirefoxでは、設定を読み込んだり書き込んだりする際には、nsIPrefまたはnsIPrefBranchが利用できました。nsIPrefは以前より廃止予定のインターフェイスでしたが、Firefox 3.7 (Gecko 1.9.3)でこのインターフェイスは削除されました。そのため拡張などでnsIPrefを未だに使用している場合は、nsIPrefBranchを利用するようにしてください。

なお、以前から利用可能だった”@mozilla.org/preferences;1″は拡張の互換性のために残していますが、nsIPrefを取得することはできません。

Linux版のIMのログをとる方法

Linux版(GTK2版)は先日、コードの分離が完了し、Windows版と同様にNSPRのログ機能を利用してログを記録できるようになりました。なお、製品版ではFirefox 4以降で可能になります。

Linuxでは環境変数を以下のように設定しておきます。

<code>export NSPR_LOG_MODULES=nsGtkIMModuleWidgets:1
export NSPR_LOG_FILE=/home/&lt;user name&gt;/fx.log
</code>

この例だと、ユーザのホームディレクトリにfx.logというファイルにログを記録します。

Windows版と同様、非常に細かいログを吐きますので、bugzillaへの提出時には最低限の操作のみを行ったログを提出してください。また、テスト終了時には必ずこれらの環境変数をリセットし、ログを取らないように修正するのを忘れないようにしてください

ところで、Linuxで更新され続けるログファイルをリアルタイムで表示してくれるソフトウェアを知らないので、教えていただけると助かります。

Jetpack Prototype から Jetpack Reboot へ

先日 Mozilla Labs Jetpack のサイトがリニューアルし、ようやく Jetpack Reboot の全貌が明るみに出てきたようですが、そもそも「Jetpack Reboot って何?今までの Jetpack とどう違うの?」と疑問に感じている方も多いかと思います。

端的に言うと、拡張機能として実験的に開発が進められてきた旧型の Jetpack (Jetpack Prototype) は近いうちに消滅し、新型の Jetpack (Jetpack Reboot) として新たにSDKへと生まれ変わる、ということになります。

ここでは、 Jetpack Prototype と Jetpack Reboot の違いを、コンセプト、構造、開発方法の3つの側面から解説したいと思います。

(1) コンセプト

Jetpack Prototype から Jetpack Reboot に変わっても、基本的なコンセプトは変わりません。 Jetpack Reboot のSDKによって作成したアドオンと、今現在広く流通している拡張機能とを比べた際の、前者の優位性として、おもに以下の事柄がコンセプトとして掲げられています。

  • Web開発者になじみのある HTML、JavaScript、CSS言語によって開発可能であること
  • APIライブラリを利用して迅速に開発可能であり、デバッグやメンテナンスがしやすいこと
  • 堅牢なセキュリティモデルによってユーザが安全に使用できること
  • Firefox本体を再起動することなくインストール、アンインストール可能であること

(2) 構造

Jetpack Prototype と Jetpack Reboot の構造を図示すると、このようになります。

Jetpack Prototype では、 Firefox 本体へAPIライブラリ+動作環境である Jetpack “拡張機能” をインストールし、その上で JavaScript で書かれた個々の小さな機能 (Jetpack Feature) を動作させる、という構造になっています。将来的には Jetpack 拡張機能の部分を Firefox 本体側に取り込む(ピンク色の点線で囲った部分全体が Firefox 本体となる)という構想もあったようです。しかし、まだ発展途上にある APIライブラリが Firefox 本体に取り込まれてしまうと、APIライブラリの迅速な開発が妨げられてしまう問題が生じます。また、すべての Jetpack Feature がAPIライブラリを共有することになりますので、各 Jetpack Feature が異なるバージョンのAPIを使用している場合に互換性の問題が生じます。

一方、Jetpack Reboot では、 Firefox 本体は Jetpack 用のAPIライブラリを持たず、個々のアドオン機能がAPIやブートローダを包含したひとつのパッケージとなっています。これにより、 APIライブラリは Firefox 本体とは独立して迅速な開発を進めることができ、個々のアドオン機能のパッケージが異なるバージョンのAPIを包含しても互いに干渉することはありません。また、このパッケージは既存の拡張機能(XULベースのアドオン)と同じXPIインストーラとして配布可能ですので、既存の拡張機能と同じようにインストール・アンインストールが可能です。さらに、将来的には Firefox 本体側の拡張機能管理システムが改良され、 Jetpack のブートローダを包含したパッケージは、 Firefox を再起動することなくインストール・アンインストール可能となる予定です。

(3) 開発方法

Jetpack Prototype から Jetpack Reboot へと変わることで、アドオン機能の開発方法は大きく変わります。
Jetpack Prototype では JavaScript のプログラムを一個記述するだけで、簡単に Feature の開発ができました。一方、 Jetpack Reboot では Jetpack SDK と呼ばれる開発環境を用い、 JavaScript のプログラムやJSON形式のマニフェストファイルなどを適切に配置してパッケージングを行う必要があります。今現在公開されている Jetpack SDK 0.1 は Python 言語で記述されたコマンドラインのツールとなっており、 Jetpack Prototype と比べると敷居が高くなったと思います。しかし、将来的には FlightDeck と呼ばれるブラウザ上で動作するGUIの開発環境により、お手軽な開発が可能となる予定です。

現時点の最新版である SDK 0.1 ではまだ使用可能なAPIが少なく、Jetpack Prototype の Feature のように色々な機能は開発できませんが、近日中に SDK 0.1 を使って Windows 7 上でパッケージングを行う手順についても解説したいと思います。

4月3日(土) に東京で Mozilla 勉強会を開催します

Firefox や Thunderbird の拡張機能や Jetpack などのアドオン、あるいはアプリケーションプラットフォームとしての Mozilla の技術についての勉強会を 04 月03日(土) に東京で開催することになりました。

/events/workshop03/

今回の Mozilla 勉強会では Jetpack Ambassadors Program に参加してきた Jetpackers (あかつかさん & Gomita さん)と、Thunderbird 3 らしい拡張機能 WAT を作成されている teramako さんをお招きしての勉強会になります。

時間割や懇親会、Lightning Talk の募集などについて詳しくは勉強会のページをご覧ください。
ご参加いただける方は ATND にてご登録をお願いします。