Dec 07, 2011

nsISessionStoreのsetTabValue()/getTabValue()がSSTabRestoringイベントの前でも使えるようになっている件

で、それを活用できるのはいつのタイミングなのよって話。

ツリー型タブはツリー構造の復元にSSTabRestoringイベントを使っているのだけれども、Firefoxのセッション復元機能はタブを1個ずつ復元していくために、100個とか大量にタブを開いているとツリー全体が復元されるまでにめちゃめちゃ時間がかかってしまうという問題がある。

これを何とかしたくて、setWindowValue()/getWindowValue()を使ってタブではなくウィンドウそのものの方にツリーの構造の情報を持たせるとかそういう事を実験してみてたんだけど、いまいち期待したような結果を得られなくて長らく放置してた。

が、最近また同じ要望が上がってて、「だから無理だって言ってんじゃん……」と思いながらその時作った実験的なコードをもう一度いじってみたら、予想に反して結構期待に近い感じで動くようになっていた。

そもそも何故過去に実験した時に期待したような結果を得られなかったかというと、SSTabRestoringイベントが発行される前のタブに対してsetTabValue()/getTabValue()をやった時の挙動が怪しかったからだった。少なくともFirefox 3.6では、SSTabRestoringイベントが発行される準備が整った時点まで待たないと、前回保存したはずの値をgetTabValue()で取れないという制限があった。それでは結局、普通にSSTabRestoringを待つしかないという事になってしまう。

それに対して今のFirefoxでは、タブが選択されるまでは内容をロードしないという機能が取り込まれていて(主にメモリの節約のためと思われる)、「セッションは完全には復元されていないが、setTabValue()/getTabValue()で情報を保存したり読み取ったりされる」という状態を考慮する必要がある。そのためいつの頃からか実装が変わって、SSTabRestoringを待たなくてもgetTabValue()で前回保存した情報を読めるようになってた。(という事に、今回初めて気がついた。)

SSTabRestoringを待たなくてもよくなった、という事は分かったんだけど、じゃあ問題はいつのタイミングでなら安心してgetTabValue()できるのかっていう事。DOMContentLoadedなのか、loadなのか、それともそこからさらにsetTimeout()で遅らせた方がいいのか? できれば早いタイミングでやりたいけど、あんまり早くやり過ぎると他の処理を壊してしまいそうで怖い。

何かヒントはないかとnsSessionStore.jsを調べたところ、sessionstore-windows-restoredまたはsessionstore-browser-state-restoredというtopicのObserver NotificationをnsIObserverとして受け取ればよさそうだということが分かった。これらはsetWindowState()された後にそのイベントループの最後で発行されるObserver Notificationで、どっちが発行されるかは場合によって変わるんだけれども、どちらも全く同じタイミングで発行されている(三項演算子でtopicだけ切り替えてるようだった)。なのでこのタイミングでgetTabValue()した情報に基づいてツリー構造を復元するようにしてみた所、無事成功してくれた。

ということで、SSTabRestoringでは物足りないという人はこれらのObserver Notificationを使うといいと思います。

エントリを編集します。

wikieditish message: Ready to edit this entry.











拡張機能