時々、あなたのコードから他の部分のあなたのコードへメッセージを送信しなければならない場合があります。例えば、タスクが完了したことを通知し、いくつかの異なる操作が実行されるようにしたい場合です。これらの関数を直接呼び出すことによって実行できますが、XPCOM が、オブザーバと observer サービスを利用するさらによい方法を提供しています。
オブザーバは、通知を監視 (待機) し、次の行動を起こすオブジェクトです。オブザーバを作成するには、 nsIObserver インタフェースを実装する必要があります。このインタフェースには、3 個の引数を取る observe()
メソッドしかありません。1 番目の引数 (監視対象) は任意の XPCOM オブジェクト、2 番目の引数は通知トピック、最後の引数は通知に使用される文字列です。
次のコードは、nsIObserver インタフェースの実装例です:
let testObserver = { observe : function(aSubject, aTopic, aData) { if (aTopic == "xulschoolhello-test-topic") { window.alert("Data received: " + aData); } } }
このオブザーバを動作させるには、オブザーバを追加、削除、通知、列挙するメソッドを提供する observer サービスを使用する必要があります。
observer サービスにオブザーバを追加するのは簡単です。 addObserver
メソッドに 3 個の引数を渡して呼び出すだけです。1 番目の引数は observer オブジェクト、2 番目の引数は通知トピック、3 番目の引数は observer サービスが observer への参照を保持するかどうかを示す真偽値です。通常は、3 番目の引数に false
を設定してください。
let observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); observerService.addObserver(testObserver, "xulschoolhello-test-topic", false);
通知トピックは、 Firefox や他の拡張機能のトピックと競合しない、ユニークなものにしなければなりません。
特定のトピックのオブザーバを削除するには、removeObserver
メソッドを使用してください。このメソッドは、引数に observer オブジェクトと通知トピックを取ります。
observerService.removeObserver(testObserver, "xulschoolhello-test-topic");
通知トピックをリッスンするためにいくつかのオブザーバを登録した後、それらすべてに通知を送るための notifyObservers
メソッドが使用できます。このメソッドは 3 個の引数を取ります。1 番目の引数はオブザーバへ渡すための任意の XPCOM オブジェクト (null も可能)、2 番目の引数は通知トピック、最後の引数はこれらのオブザーバへ渡す追加の文字列 (null
も可能) です。
observerService.notifyObservers(null, "xulschoolhello-test-topic", "hello");
非 chrome と chrome の間のコミュニケーション
非 chrome と chrome の間のコミュニケーションは、オブザーバの主な使用目的の一つです。非 chrome は、JavaScript コードモジュール (JSM) や XPCOM を意味します。前回のセクションで見てきたように、JSM と XPCOM オブジェクトは、chrome からとても簡単に利用できます。しかし、与えられた chrome は window 依存ですが、非 chrome オブジェクトはそうではありません。chrome にメッセージを送るにはコツがいります。すべての window の chrome オブジェクトに対してメソッドを呼び出さなければならないでしょう。このような場合は、オブザーバを使うことで簡単にできます。
非 chrome のコードから通知をどのように送るかを次のコード例で見てみましょう。
/** * テスト通知トピックで登録されたすべてのオブザーバに通知する */ notifyTest : function() { let observerService = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let subject = Cc["@mozilla.org/supports-string;1"]. createInstance(Ci.nsISupportsString); // data 属性に文字列を割り当てる subject.data = "This is a test."; // 登録されたすべてのオブザーバに通知する observerService.notifyObservers( subject, "xulschoolhello-test-topic", "hello"); }
notifyTest
メソッドでは、 "xs-hw-test-topic" 通知トピックについて登録されたすべてのオブザーバに対して通知するために notifyObservers
が呼び出されます。入力引数は、短いテキストを持つ nsISupportsString
のインスタンスと "Hello" 文字列です。
chrome の browser オーバーレイファイルでは、window が読み込まれた時に "xs-hw-test-topic" 通知トピックをリッスンするオブザーバを登録します。必要なくなったオブザーバは削除しなければならないことを心に留めてください。削除しなければメモリリークを起こします。そのため、登録されたオブザーバは、browser ウィンドウが閉じられると登録解除されます。
/** * Hellow World 拡張のための browser オーバーレイの制御 */ XULSchoolChrome.BrowserOverlay = { /* Observer サービス */ _observerService : null, /** * このオブジェクトの初期化 */ init : function() { this._observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); this._observerService.addObserver(this, "xulschoolhello-test-topic", false); }, /** * このオブジェクトの後始末 */ uninit : function() { this._observerService.removeObserver( this, "xulschoolhello-test-topic"); }, /** * 登録された通知トピックの監視 * @param aSubject : 通知に関連付けられた nsISupports オブジェクト * @param aTopic : 通知トピック * @param aData : 通知に関連付けられた追加の文字列 */ observe : function(aSubject, aTopic, aData) { if (aTopic == "xulschoolhello-test-topic") { aSubject.QueryInterface(Ci.nsISupportsString); window.alert("Subject: " + aSubject.data); // => "This is a test" window.alert("Data: " + aData); // => "Hello" } } } window.addEventListener( "load", function() { XULSchoolChrome.BrowserOverlay.init(); }, false); window.addEventListener( "unload", function() { XULSchoolChrome.BrowserOverlay.uninit(); }, false);
1 つのオブザーバでいくつものトピックをリッスンできるため、observe
メソッドでは通知トピックを検証しています。 QueryInterface
メソッドを使用して、 aSubject
オブジェクトのインタフェースを nsISupportsString
に明示的に設定していることに気付いたでしょうか。これは、 observe
メソッドの 1 番目の引数の型が nsISupports
(前に見たように一般的なインタフェースです) であるため、正しいインタフェースを設定しないと、そのプロパティやメソッドへアクセスできないためです。
notifyTest
メソッドが呼び出されると、xulschoolhello-test-topic で登録されたすべてのオブザーバが通知を受け取り、2 つの警告を表示します。Firefox のウィンドウが 2 つ開いているときは、オブザーバが両方のウィンドウへ通知され、両方のウィンドウで警告が表示されます。
いつでも、同じオブザーバを使用して複数の通知トピックをリッスンすることができます。また、同じオブザーバに何度も通知トピックを追加しないように注意してください。同じオブザーバに複数の通知トピックを追加してしまうと、オブザーバ内の同じコードによって、何度も通知が送られてしまいます。
役立つ Firefox の通知
このセクションでは、オブザーバと observer サービスを使用してカスタム通知トピックを送受信する方法を扱いました。Firefox には多くの埋め込まれたオブザーバトピックがあり、それらを同じように監視することができます。 Observer Notifications のページに、いくつかの役立つトピックの一覧があります。これらは時間をかけて学んでおく価値があります。
This tutorial was kindly donated to Mozilla by Appcoast.