Implementing XPCOM components in JavaScript: Difference between revisions
From MozillaZine Knowledge Base
Jump to navigationJump to search
Richwklein (talk | contribs) |
Richwklein (talk | contribs) |
||
Line 13: | Line 13: | ||
== Finished Code == | == Finished Code == | ||
Below is how the finished code may look. | |||
<pre> | <pre> | ||
// constants | |||
const nsISupportsPriority = Components.interfaces.nsISupportsPriority; | const nsISupportsPriority = Components.interfaces.nsISupportsPriority; | ||
const CLASS_ID = Components.ID("{1C0E8D86-B661-40d0-AE3D-CA012FADF170}"); | const CLASS_ID = Components.ID("{1C0E8D86-B661-40d0-AE3D-CA012FADF170}"); | ||
Line 20: | Line 23: | ||
const CONTRACT_ID = "@mozillazine.org/example/priority;1"; | const CONTRACT_ID = "@mozillazine.org/example/priority;1"; | ||
//class constructor | |||
function MyPriority() { | function MyPriority() { | ||
this._priority = nsISupportsPriority.PRIORITY_LOWEST; | this._priority = nsISupportsPriority.PRIORITY_LOWEST; | ||
}; | }; | ||
//class definition | |||
MyPriority.prototype = { | MyPriority.prototype = { | ||
_priority: null, | _priority: null, | ||
Line 43: | Line 48: | ||
}; | }; | ||
//class factory | |||
var MyPriorityFactory = { | |||
createInstance: function (aOuter, aIID) | |||
{ | |||
if (aOuter != null) | |||
throw Components.results.NS_ERROR_NO_AGGREGATION; | |||
return (new MyPriority()).QueryInterface(aIID); | |||
} | |||
}; | |||
//module definition (xpcom registration) | |||
var MyPriorityModule = { | var MyPriorityModule = { | ||
_firstTime: true, | _firstTime: true, | ||
Line 75: | Line 91: | ||
}; | }; | ||
//module initialization | |||
function NSGetModule(aCompMgr, aFileSpec) { return MyPriorityModule; } | function NSGetModule(aCompMgr, aFileSpec) { return MyPriorityModule; } | ||
</pre> | </pre> |
Revision as of 21:51, 2 February 2006
About XPCOM
Mozilla applications are built from a collection of XPCOM (Cross-platform Component Object Model) objects. They are used to perform certain tasks or to get specific functionality. For example, there is a directory service component that can be used to access files on your file system. Components can be constructed using several programming languages, including: javascript, c++, and python. Mozilla then uses "interfaces" to describe what a component can do. The most basic interface nsISupports is used to get different interfaces that a component implements.
- Benifits of XPCOM
- XPCOM objects can be used by any programming language mozilla supports.
- Objects implemented as XPCOM are global to an application, and are not dependent on the scope of any one window.
- Programming logic can be encapsulated within an object.
- XPCOM Drawbacks
- Objects must be accessed from their defined interfaces. Javascript shortcuts such as the global window object cannot be accessed.
- The only exception to this rules, is if you set a magical property wrappedJSObject equal to your component, then the underlining javascript object can be accessed.
- It is easier to have memory leaks
- Objects must be accessed from their defined interfaces. Javascript shortcuts such as the global window object cannot be accessed.
Finished Code
Below is how the finished code may look.
// constants const nsISupportsPriority = Components.interfaces.nsISupportsPriority; const CLASS_ID = Components.ID("{1C0E8D86-B661-40d0-AE3D-CA012FADF170}"); const CLASS_NAME = "My Supports Priority Component"; const CONTRACT_ID = "@mozillazine.org/example/priority;1"; //class constructor function MyPriority() { this._priority = nsISupportsPriority.PRIORITY_LOWEST; }; //class definition MyPriority.prototype = { _priority: null, get priority() { return this._priority; }, set priority(aValue) { this._priority = aValue; }, adjustPriority: function(aDelta) { this._priority += aDelta; }, QueryInterface: function(aIID) { if (!aIID.equals(nsISupportsPriority) && !aIID.equals(Components.interfaces.nsISupports)) throw Components.results.NS_ERROR_NO_INTERFACE; return this; } }; //class factory var MyPriorityFactory = { createInstance: function (aOuter, aIID) { if (aOuter != null) throw Components.results.NS_ERROR_NO_AGGREGATION; return (new MyPriority()).QueryInterface(aIID); } }; //module definition (xpcom registration) var MyPriorityModule = { _firstTime: true, registerSelf: function(aCompMgr, aFileSpec, aLocation, aType) { if (this._firstTime) { this._firstTime = false; throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN; }; aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar); aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType); }, unregisterSelf: function(aCompMgr, aLocation, aType) { aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar); aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation); }, getClassObject: function(aCompMgr, aCID, aIID) { if (!aIID.equals(Components.interfaces.nsIFactory)) throw Components.results.NS_ERROR_NOT_IMPLEMENTED; if (aCID.equals(CLASS_ID)) return MyPriorityFactory; throw Components.results.NS_ERROR_NO_INTERFACE; }, canUnload: function(aCompMgr) { return true; } }; //module initialization function NSGetModule(aCompMgr, aFileSpec) { return MyPriorityModule; }