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
}]