Now browsing the SCRAPBLOG weblog archives.

[Exception… “‘Component is not available’ when calling method: [nsIHandlerService::getTypeFromExtension]

2008/5/3 追記
この問題は解決済みです。

Firefox 3にて、XULから <script type="application/x-javascript" src="chrome://myext/content/test.js" /> のようにして JavaScript を読み込む際、その JavaScript ファイルがjar形式アーカイブの中身ではなくて純粋なローカルファイルである場合(つまり chrome.manifest にて content myext content/myext/ のようにしている場合)、以下の例外がエラーコンソールに出力される。

エラー: [Exception… “‘Component is not available’ when calling method: [nsIHandlerService::getTypeFromExtension]” nsresult: “0x80040111 (NS_ERROR_NOT_AVAILABLE)” location: “” data: no]

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9pre) Gecko/2008042606 Minefield/3.0pre

TOP

タブの複製機能

Firefox 3 (Minefield) で新たに追加されたタブの複製機能(Ctrl キーを押下しながらのタブのドラッグ&ドロップ)が、戻る・進むの履歴などのセッション状態も含めてタブを複製できるようになった。

これに伴い、 nsISessionStore インタフェースに以下の3メソッドが追加された。

メソッド 概要
duplicateTab() 指定したタブを、セッション状態も含めて複製する
getTabState() 指定したタブのセッション状態を JSON 文字列として取得する
setTabState() タブのセッション状態を表す JSON 文字列からタブを復元する

duplicateTab はすでに閉じたタブの状態を復元するのではなく、現在開いているタブの状態を複製する機能なので、 browser.sessionstore.enabled が false でも動作するようだ。

nsISessionStore::duplicateTab 使用例

// an example code to duplicate |tab| in the current window
var newTab;
try {
    newTab = Cc["@mozilla.org/browser/sessionstore;1"]
             .getService(Ci.nsISessionStore)
             .duplicateTab(window, tab);
}
catch (ex) {
    // fall-back
    newTab = gBrowser.loadOneTab(gBrowser.getBrowserForTab(tab).currentURI.spec);
}

xul:tabbrowser 要素自体に定義された duplicateTab メソッドがまさに上記のことをやっているので、これを使う方が手っ取り早い。

var newTab = gBrowser.duplicateTab(tab);

参考

Bug 393716 – Add single tab save/restore to session store API

TOP

nsIPopupBoxObject::setConsumeRollupEvent (2)

前の記事に書いた時点では、 Firefox 3 で新たに追加された nsIPopupBoxObject::setConsumeRollupEvent メソッドは Windows でのみ動作し、 Linux と Mac OS X では効果が無かった。

Linuxのその後の状況

1月11日にLinuxで動作しない件についてバグを立てた。
Bug 411903 – nsIPopupBoxObject#setConsumeRollupEvent has no effect on Linux
1月20日頃、以下のバグへのパッチ適用に伴い、Linuxでもめでたく正常動作するようになった。
Bug 188126 – gtk2: autocomplete/popup widgets should not block clicks outside of themselves

Mac OS Xのその後の状況

2月3日にMac OS Xで動作しない件についてバグを立てた。有識者による確認待ち。
Bug 415440 – nsIPopupBoxObject#setConsumeRollupEvent has no effect on Mac OS X
Neal Deakin 氏によると、 Mac OS X では単純にまだ実装されていないだけのようだ。

TOP

nsIPopupBoxObject::setConsumeRollupEvent

ポップアップを開いた状態でポップアップの外側のどこかをクリックしたときの挙動は、ウィジェットやプラットフォームに依存する。わかりやすい例として、コンテントエリア内で右クリックメニューを開き、そのままページ内のどこかのハイパーリンクをクリックすると、

プラットフォーム 挙動
Windows ポップアップが閉じ、リンク先へ遷移する
Linux ポップアップが閉じるだけ
Mac ポップアップが閉じるだけ

これに対して、検索バーの検索エンジンのドロップダウンリストを開いた状態で、コンテントエリア内のハイパーリンクをクリックしたときの挙動は、プラットフォームによらずドロップダウンリストが閉じるだけで、リンク先へは遷移しない。

このように、ポップアップの外側をクリックしたときにポップアップを自動で閉じる(ロールアップする)だけで、実際にクリックした何かに対するクリックイベントが発生しないような挙動のことを、「クリックの横取り」と呼ぶ。クリック横取りに関する動作仕様の詳細は、 nsMenuPopupFrame::ConsumeOutsideClicks のソース内に記載されており、通常は以下のルールに従った挙動となる。

ウィジェットの種類 ポップアップの親要素 挙動
メニュー <menu> か <popupset> Windows: クリックの横取りなし
Linux / Mac: クリックの横取りあり
オートコンプリート <textbox type=”autocomplete”> プラットフォームによらず、クリックの横取りなし
コンボボックス <menulist> プラットフォームによらず、クリックの横取りあり

Firefox 3 では新たに追加された nsIPopupBoxObject::setConsumeRollupEvent メソッドを使って、クリックの横取りの動作仕様を無理やり変更できるようになった。このメソッドの引数は3種類あり、0(デフォルト、ウィジェット・プラットフォーム依存)、1(クリックの横取りを強制的にありにする)、2(クリックの横取りを強制的になしにする)の3種類が指定可能である。実際に試すために以下の手順を試す。

  1. テストケースを開く
  2. [ROLLUP_DEFAULT] ボタンをクリックしてポップアップを開く
  3. ポップアップを開いたまま [TEST] ボタンをクリックする
  4. [ROLLUP_CONSUME] ボタンについても同様に手順2~3を繰り返す
  5. [ROLLUP_CONSUME] ボタンについても同様に手順2~3を繰り返す

すると、 Windows + Firefox 3.0b3pre では期待通り以下の結果が得られたものの、 Linux / Mac + Firefox 3.0b3pre では期待に反した結果となった。

最初に押下するボタン プラットフォーム [TEST] ボタン押下後の挙動
[ROLLUP_DEFAULT] Windows ポップアップが閉じるだけ
Linux ポップアップが閉じるだけ
Mac ポップアップが閉じるだけ
[ROLLUP_CONSUME] Windows ポップアップが閉じるだけ
Linux ポップアップが閉じるだけ
Mac ポップアップが閉じるだけ
[ROLLUP_NO_CONSUME] Windows ポップアップが閉じてダイアログが表示
Linux ポップアップが閉じるだけ
Mac ポップアップが閉じるだけ

どうやら Linux / Mac では nsIPopupBoxObject#setConsumeRollupEvent の引数に ROLLUP_NO_CONSUME を渡したときの効果が何も無いようなので、 Bugzilla へバグを立ててみた。ここまで自分が述べたことに確信を持っているわけではないので、有識者の判断を待つこととする。

Bug 411903 – nsIPopupBoxObject#setConsumeRollupEvent has no effect on Linux

関連記事

Firefox 3 でのポップアップ仕様変更
nsIPopupBoxObject::enableRollup
nsIPopupBoxObject::enableKeyboardNavigator

TOP

JavaScript コードモジュール

Using JavaScript code modules – MDC の和訳が完了した。
「JavaScript コードモジュール」とは、 Firefox 3 の JavaScript 製 XPCOM で頻繁に見かける以下のようなやつのことです。

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

上記の例のように共通で使用するユーティリティ的な関数群をモジュール化して、色々な場所からインポートして利用することができるだけでなく、あらゆる JavaScript のスコープで共有可能なシングルトンのオブジェクトとしての利用も可能です。今までは同様のことを実現するためには JavaScript 製 XPCOM の定義が必要であり、若干敷居が高かった。

まあ Firefox 3 以降ということで実践投入はだいぶ先のことになりそうだが、 JavaScript コードモジュールによって拡張機能の実装方式の自由度が高まることは間違いないでしょう。

TOP

FUEL 2.0

FUEL – MDC からリンクされている全オブジェクトのページの和訳が完了した。
以下、 FUEL 2.0 で追加された各オブジェクトについての雑感。

Window

ブラウザウィンドウの新しいタブでURIを開く。
タブを開く・閉じる・移動する・選択するイベントを監視する。
ブラウザウィンドウを開いた直後(つまり browser.xul にて window の load イベント発生時)に、イベントリスナを追加するために、 Application.activeWindow.events.addListener… などとやりたいところだが、アクティブなウィンドウ=今開いたウィンドウとは限らない?つまり、バックグラウンドでウィンドウを開くようなケースもありうるかも?

BrowserTab

タブでURIを読み込む、タブを移動する、タブを選択する、タブの内容ドキュメントを取得する。
タブへの読み込みイベントを監視する。
Window#open と BrowserTab#load は使用頻度高そうだが、引数はどちらも nsIURI オブジェクトってのは痛い。 FUEL の目的は XPCOM を意識しない形へとコードを簡略化することじゃなかったっけ?

BookmarkFolder

Bookmark

ブックマーク・区切り・フォルダの追加、削除、各プロパティの取得と変更。機能的にはそれだけ。
BookmarkFolder#addSeparator の引数にタイトルを指定できないのはなぜ?と思ったら、 Places では区切りにタイトルを付けられなくなっているようだ。

Annotations

Places:Annotation Service 自体は拡張機能開発者的にはかなり期待できそうなシステムだけど、 FUEL の Annotations オブジェクトによってどういうメリットがもたらされるかは現時点では不明。

TOP

Firefox 3 のフルページズーム使用時はスクリーン上でのピクセル量とCSS上でのピクセル量は一致しない

Firefox 3 Alpha に搭載されたフルページズーム(テキストと画像をともに拡大/縮小する機能)を使った場合、CSS レイアウトの座標上での「1ピクセル」という単位は、必ずしも画面上での1ピクセルに一致しないことになる。例えばフルページズーム機能でページを2倍に拡大した状態だと、CSSでの1pxのborderがスクリーン上では2pxとして表示される(下図参照)。

左:Firefox 2.0.0.5 で「文字サイズ」を約2倍に拡大した表示例
右:Firefox 3.0a8pre でフルページズームを使って2倍に拡大した表示例
Full Zoom

問題が生じるケース

All-in-One Gestures のマウストレイル(マウスジェスチャの軌跡描画機能)は、マウスポインタの移動に応じてスクリーン上の座標 (event.screenX, event.screenX) が変化したピクセル量分だけの点をページ上に配置することによって線を描画するという仕様である。
フルページズームでページを2倍に拡大した状態だと、スクリーン上の座標で4px移動しても、実際のCSSの座標上では2px分という計算になるが、現時点の AiOG のマウストレイルの実装はこれを考慮していない。したがって、 AiOG を無理やり Firefox 3 上で使用すると、スクリーン上の座標で4px移動したときもCSSの座標上で4px分の点を配置するため、実際のスクリーン上では8pxとして表示されてしまう。なおかつ、線の太さが2倍になる、軌跡の位置がマウスポインタから大きくずれるといった問題点が生じる。

結論

フルページズーム機能搭載に伴い、スクリーン上でのピクセル量とCSS上でのピクセル量が一致するという前提はもはや崩れ去った。両者の整合性を取るためには、 nsIMarkupDocumentViewer::fullZoom 値を常に意識する必要がある。例えば現在フォーカスしているブラウザの fullZoom 値は、以下のようにして取得可能である。

gBrowser.mCurrentBrowser.markupDocumentViewer.fullZoom

TOP