Firefox の拡張機能で全てのウィンドウで共通の 1 つの処理を行う (または異なるウィンドウ間で情報の共有を行う)

Firefox拡張機能の話。 バックグラウンドで行うべき何らかの処理 *1 があるとします。 以下のように load イベントを捕捉してその処理を起動すると、新しくウィンドウ ((ここでいうウィンドウとは、JavaScript のグローバルオブジェクト (window) を新たに作るもののことを言います。 詳しくは chrome コードでウィンドウを取り扱う方法を述べた文書 を見てください。)) を開くたびにそのバックグラウンドの処理が行われてしまいます。

/** 名前空間用オブジェクト */
var myapp = {};
/** バックグラウンドで行う処理を起動する関数 */
myapp.launch_background_proc = function() { ... };
/** 初期化用関数 */
myapp.onLoad = function(evt) {
    myapp.launch_background_proc();
};
// ブラウザの新しいウィンドウを開くたびにイベント発生
// (XUL の overlay 要素の中で実行した場合)
window.addEventListener( "load", myapp.onLoad, false );

これが望む動作なのであればいいのですが、全てのウィンドウで 1 つの処理を共有させたい (つまり、2 個目以降のウィンドウを開いた場合には新たにバックグラウンドで行う処理を起動したくない) 場合 *2 には違う方法を採らなければいけません。 ここではそれを簡単に行うための方法を紹介します。

JavaScript コードモジュールを使う

全てのウィンドウで共通の 1 つの処理を行うための方法はいくつかあります。 例えば、既に起動しているウィンドウを全て調べ (nsIWindowMediator を使用) て、バックグラウンドで実行する処理がまだ起動されていない場合だけ新たに起動する、という方法でもできなくはありません。 しかし一番簡単なのは JavaScript コードモジュールを使う方法だと思います。

JavaScript コードモジュールを使うと、特権を持った全てのスコープで共通の JavaScript オブジェクトを生成できます。 すなわち、わざわざ他の全てのウィンドウを調べて既にバックグラウンドで行う処理が起動されているかどうかを調べる、などということはせずに、JavaScript コードモジュールのオブジェクトに情報を持たせておき、それを見て起動するかどうか決める、ということができます。

使用方法

詳しい使用方法は以下にあります。

*1:例えば、API を使用して絶えず twitter と通信を行い、常に最新の情報を保持しておくような処理。

*2:例えば twitter との通信を例に考えると、最新の情報は 1 箇所で保持しておけば良い (複数のウィンドウで別々に情報を保持しておく必要はない) ので、全てのウィンドウで 1 つの処理を共有させるのが良いでしょう。