Components.classes は、プロパティが ContractID によって索引付けされたクラスである、読み出し専用オブジェクトです。


Components.classes は、nsIJSCID インターフェースを実装した読み出し専用オブジェクトです。それぞれのオブジェクトは、XPCOM サービスとして構築またはアクセスされうる XPCOM コンポーネントのクラスのひとつを表します。

このオブジェクトのプロパティは、コンポーネントクラスの ContractID (または人間が読める形式の名前) で索引付けされています。

All of the properties and methods of the nsIJSCID and its ancestor interface nsIJSID are available for use on the objects contained in this object.

Note that Components.classes reflects only those component classes that have been previously installed and registered with the component manager using ContractIDs. If you want to use a class which was only registered with their CID, use Components.classesByID instead of Components.classes to retrieve it.

あるマシンには ContractID を指定されたアドオンコンポーネントが存在し、別のマシンにはインストールされていないこともあり得ます。Components.classes は、以前にインストールされ ProgId を用いてコンポーネントマネージャに登録されたコンポーネントクラスのみを反映します。ですから、あるマシンには ProgID を指定されたアドオンコンポーネントが存在し、別のマシンにはインストールされていないこともあり得ます。Components.classes オブジェクトに与えられた要素がそのマシンに登録されていない場合、その要素にアクセスを試みると、ストリクトモードでは JavaScript の警告が生成され、戻り値は JavaScript の undefined になります。要素にアクセスする際は、あらかじめ in オペレータを使って、その要素をテストするべきです。

if (!("@some/bogus/class;1" in Components.classes))
  // do something...

Components.classes オブジェクトのプロパティは ループを使って列挙できます。


与えられた ContractID のためのオブジェクトを取得する

In order to retrieve the object for a given ContractID, you can query the Components.classes array as follows:

var clazz0 = Components.classes[";1"];
var clazz1 = Components.classes[";1"];

The first line will return you the class object for the ContractID;1, the second line will return you the class object for the ContractID;1.

It may be helpful to abbreviate Components.classes by storing a reference to the object as a constant:

// use whatever name suits your fancy -- Cc is probably the most common abbreviation
const Cc = Components.classes;
const C = Components.classes;

var clazz0 = Cc[";1"];
var clazz1 = C[";1"];

XPCOM コンポーネントのインスタンスを作成する

An XPCOM component instance can be created from the returned class object as follows:

var clazz = Components.classes[";1"];
var obj   = clazz.createInstance();

createInstance() calls will return XPConnect wrappers for these native objects which only expose the methods of the nsISupports interface. This is because the specific interface on the component that the caller desires has not been specified. Specifying that interface is done using the properties of the Components.interfaces object:

var obj = Components.classes[";1"]

which is equivalent to:

var obj = Components.classes[";1"];

Alternatively, you can use the new operator on the class object to create a new instance of that class:

var clazz = Components.classes[";1"];
var inst  = new clazz(Components.interfaces.nsISupportsArray);

This implicitly calls the createInstance() method for you.

XPCOM サービスコンポーネントへのアクセス


var clazz = Components.classes[";1"];
var obj   = clazz.getService();

getService() は、createInstance() のように、ネイティブオブジェクトへの XPConnect ラッパーを返し、nsISupports インターフェースのメソッドのみを見せます。これは、呼び出し側の求めるコンポーネント上の特殊なインターフェースが特定されないようにするためです。このインターフェースの指定は、Components.interfaces オブジェクトの要素を使って行います。

var clazz = Components.classes[";1"]
var srv   = clazz.getService(Components.interfaces.nsIPref);


var clazz = Components.classes[";1"]
var obj   = clazz.getService();
var srv   = obj.QueryInterface(Components.interfaces.nsIPref);


It is not possible to programmatically determine if a given component has to be instantiated or used as a service.

Often, this is stated in the documentation of the component you want to use. If this is not the case, you might want to try and find example usages of that component within LXR.