XPCOMUtilsを使おう
Firefox3でしか使えませんが、
Firefox拡張機能開発で、
- QueryInterface
- NSGetModule
メソッドを書くとき、やたら長いコードを毎回書かなくてはならず、めんどくさくてしょうがない方のためのモジュールです。
https://developer.mozilla.org/Ja/XPCOMUtils.jsm
http://mxr.mozilla.org/mozilla/source/js/src/xpconnect/loader/XPCOMUtils.jsm
ソースコードに使い方が書いてありますが、改めて説明。
XPCOMUtilsを読み込む
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
QueryInterface の書き方
XPCOMUtils.generateQI([Components.interfaces.nsIRunnable]);
これだけで、QueryInterfaceの処理を実行してくれるFunctionオブジェクトを生成してくれます。
インターフェースを複数指定する場合は,配列に並べるだけ。
nsISupportsは暗黙的に追加されます。
NSGetModule の書き方
JS XPCOMを作る場合に, NSGetModuleメソッドを作ることになりますが、この手順をXPCOMUtilsで省略できます。
// XPCOMの実装 function MyComponent{} MyComponent.prototype = { classDescription: "クラスの説明", classID: Components.ID('{GUIDをここに書く}'), contractID: "@example.com/mycomponent;1", // _xpcom_factory: オプション, // _xpcom_categories: オプション, QueryInterface: XPCOMUtils.generateQI([Components.interfaces.myIComponent]) } // NSGetModuleを定義 function NSGetModule(aCompMgr, aFileSpec) { return XPCOMUtils.generateModule([MyComponent]); }
という感じ。お手軽です。
ちなみに, XPCOMUtils.generateNSGetModule という NSGetModule を定義するメソッドも用意されてます。
ソースコードの説明では, なぜかこっちを使っていませんでした。
オプションと書いている, _xpcom_factory と _xpcom_categories について。
_xpcom_factory は createInstance で実行されるコードを記述できます。
XPCOMのサービスを定義する場合にSingletonで実装しておきたい・・・などの場合に使えます。
デフォルトの動作で書いてみると、
_xpcom_factory : { createInstance: function(aOuter, aIID) { return (new MyComponent()).QueryInterface(aIID); }, QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIFactory]) }
という実装になるようです。
「カスタムファクトリを私用する場合, オブジェクトは nsIFactory を実装している必要があるよ」
と書いてありますので, 一応 QueryInterface で nsIFactory を定義しています。
_xpcom_categories は、 nsICategoryManager.addCategoryEntry()に渡すパラメータを指定するようです。
char* addCategoryEntry ( char* category , char* entry , char* value , PRBool persist , PRBool replace )
http://www.xulplanet.com/references/xpcomref/ifaces/nsICategoryManager.html
nsICategoryManager.addCategoryEntry()の役割を把握してないので、
ソースコードの説明を貼り付けておきます。ついでに訳してみます。
_xpcom_categories: [{ // Each object in the array specifies the parameters to pass to // nsICategoryManager.addCategoryEntry(). 'true' is passed for // both aPersist and aReplace params. // 配列中の各オブジェクトの示すパラメータを // nsICategoryManager.addCategoryEntry() に渡します. // パラメータの aPersist と aReplace には 'true' が渡されます. category: "some-category", // optional, defaults to the object's classDescription // オプション: デフォルトは オブジェクトの classDescription を使います. entry: "entry name", // optional, defaults to the object's contractID (unless // 'service' is specified) // オプション: デフォルトは オブジェクトの contractID を使います. // ( (下の) 'service'が指定されない場合) value: "...", // optional, defaults to false. When set to true, and only if 'value' // is not specified, the concatenation of the string "service," and the // object's contractID is passed as aValue parameter of addCategoryEntry. // オプション: デフォルトではfalseです. trueを指定し, (上の)'value'を指定しない場合, // 文字列 "service," を連結したオブジェクトの contractID を // addCategoryEntry の aValueパラメータに渡します。 service: true }]