タブの複製機能

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

拡張機能が設定値「browser.sessionstore.restore_prompt_uri」を変更することの危険性

先日開催された Firefox Developers Conference 2006 の個別セッションのコーナーにて、設定値「browser.sessionstore.restore_prompt_uri」を変更することで、クラッシュからのセッション回復時に拡張機能が独自にこしらえたプロンプトを使用することが可能となる、という話をして、実際にカウントダウン式のセッション回復プロンプトを動かすデモを行った。
これに関してPiroさんから、「拡張機能を削除して変更した設定値がそのまま残ってしまった場合、何らかのフォールバックはあるのか?」という指摘を頂いた。

調べてみたところ、nsSessionStartup.js の250行目あたりからを見ると、セッション回復プロンプトを開く処理は nsIWindowWatcher::openWindow() メソッドによって実行されていることがわかる。このメソッドの引数として「browser.sessionstore.restore_prompt_uri」の値を渡してウィンドウを開くのであるが、その値によって以下のような挙動となる。

存在するchrome: URI ウィンドウが開き、XULなどがロードされる。例えば、拡張機能独自のプロンプトが開かれる。
存在しないchrome: URI ウィンドウは開かず、何も起こらない。処理は先に進まない。
空の文字列 標準のセッション回復プロンプトが開かれる。
http: URI ウィンドウが開いてWebページがロードされる。ウィンドウのxボタンをクリックして閉じれば、セッションが回復する。
明らかにURIではない文字列 プロンプトは開かれず、セッションが回復する。これは openWindow メソッドで発生した例外をキャッチするフォールバック処理があるため。

やはり問題となるのは、拡張機能を削除した場合に存在しないchrome: URIが設定値として残ってしまうケースだろう。この場合の危険性は以下のような話に例えることができる。

Firefox 初級ユーザであるA君は、「Countdown Recovery」という拡張機能をインストールした。
すると設定値「browser.sessionstore.restore_prompt_uri」が「chrome://countdownrecovery/content/prompt.xul」に変更され、クラッシュからのセッション回復時に当該URIのプロンプトが開かれるようになった。
しばらくしてA君はこの拡張機能が気に入らなくなったので、アンインストールした。このとき、変更された設定値がそのまま残ってしまったことに、A君は当然気付くはずもなかった。
後日A君の Firefox がクラッシュしたため再起動したところ、何度試しても Firefox のブラウザウィンドウは開かれなかった。不思議に思ったA君は Firefox を再インストールしたが、結果は同じ。
困ったA君は Firefox 中級ユーザであるB君に助けを求め、セーフモードで起動しろというアドバイスに従って試したが、やはり Firefox のウィンドウは出現しない。これにはB君もお手上げ状態で、最後の手段としてプロファイルを作り直すしかないと判断した。A君は新しいプロファイルを作ることでようやく Firefox を起動することに成功したが、泣く泣くカスタマイズを一からやり直すこととなった。

この例え話で起こった症状は、Firefox を終了させた状態で prefs.js に書き込まれている問題の設定値を削除するか、あるいは sessionstore.js および sessionstore.bak を削除した上でセッション回復させずに Firefox を再起動し、about:config から設定値をリセットすることで解決される。

一般に、拡張機能をアンインストールしても、prefs.js に書き込まれたその拡張機能に関係する設定値などはそのまま残ってしまう。また、拡張機能が独自に生成したファイルなどのデータも当然残ったままだ。しかし、Piroさんの話では NoScript という拡張機能ではアンインストール時に何らかの処理を行う仕掛けがあるそうなので、さっそく調べてみた。

TOP