Bug 386536 - Add category manager helpers to XPCOMUtils. Patch by Nickolay Ponomarev <asqueella@gmail.com>, r=sayrer/mark.finkle a=jst

This commit is contained in:
rflint@ryanflint.com 2007-08-23 17:21:10 -07:00
parent 672757f230
commit d9e5356f9c
2 changed files with 76 additions and 65 deletions

View File

@ -1103,12 +1103,26 @@ BookmarkFolder.prototype = {
},
QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBookmarkFolder, Ci.nsINavBookmarkObserver])
};
};
//=================================================
// Factory - Treat Application as a singleton
// XXX This is required, because we're registered for the 'JavaScript global
// privileged property' category, whose handler always calls createInstance.
// See bug 386535.
var gSingleton = null;
var ApplicationFactory = {
createInstance: function af_ci(aOuter, aIID) {
if (aOuter != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
const CLASS_ID = Components.ID("fe74cf80-aa2d-11db-abbd-0800200c9a66");
const CLASS_NAME = "Application wrapper";
const CONTRACT_ID = "@mozilla.org/fuel/application;1";
if (gSingleton == null) {
gSingleton = new Application();
}
return gSingleton.QueryInterface(aIID);
}
};
//=================================================
// Application constructor
@ -1135,6 +1149,23 @@ function Application() {
//=================================================
// Application implementation
Application.prototype = {
// for nsIClassInfo + XPCOMUtils
classDescription: "Application",
classID: Components.ID("fe74cf80-aa2d-11db-abbd-0800200c9a66"),
contractID: "@mozilla.org/fuel/application;1",
// redefine the default factory for XPCOMUtils
_xpcom_factory: ApplicationFactory,
// get this contractID registered for certain categories via XPCOMUtils
_xpcom_categories: [
// make Application a startup observer
{ category: "app-startup", service: true },
// add Application as a global property for easy access
{ category: "JavaScript global privileged property" }
],
get id() {
return this._info.ID;
},
@ -1194,9 +1225,6 @@ Application.prototype = {
},
// for nsIClassInfo
classDescription : "Application",
classID : CLASS_ID,
contractID : CONTRACT_ID,
flags : Ci.nsIClassInfo.SINGLETON,
implementationLanguage : Ci.nsIProgrammingLanguage.JAVASCRIPT,
@ -1267,61 +1295,7 @@ Application.prototype = {
}
};
//=================================================
// Factory - Treat Application as a singleton
var gSingleton = null;
var ApplicationFactory = {
createInstance: function af_ci(aOuter, aIID) {
if (aOuter != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
if (gSingleton == null) {
gSingleton = new Application();
}
return gSingleton.QueryInterface(aIID);
}
};
//=================================================
// Module
var ApplicationModule = {
registerSelf: function am_rs(aCompMgr, aFileSpec, aLocation, aType) {
aCompMgr = aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType);
var categoryManager = Components.classes["@mozilla.org/categorymanager;1"]
.getService(Ci.nsICategoryManager);
// make Application a startup observer
categoryManager.addCategoryEntry("app-startup", CLASS_NAME, "service," + CONTRACT_ID, true, true);
// add Application as a global property for easy access
categoryManager.addCategoryEntry("JavaScript global privileged property", "Application", CONTRACT_ID, true, true);
},
unregisterSelf: function am_us(aCompMgr, aLocation, aType) {
aCompMgr = aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);
// cleanup categories
var categoryManager = Components.classes["@mozilla.org/categorymanager;1"]
.getService(Ci.nsICategoryManager);
categoryManager.deleteCategoryEntry("app-startup", "service," + CONTRACT_ID, true);
categoryManager.deleteCategoryEntry("JavaScript global property", CONTRACT_ID, true);
},
getClassObject: function am_gco(aCompMgr, aCID, aIID) {
if (!aIID.equals(Ci.nsIFactory))
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
if (aCID.equals(CLASS_ID))
return ApplicationFactory;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
canUnload: function am_cu(aCompMgr) { return true; }
};
//module initialization
function NSGetModule(aCompMgr, aFileSpec) { return ApplicationModule; }
function NSGetModule(aCompMgr, aFileSpec) {
return XPCOMUtils.generateModule([Application]);
}

View File

@ -60,7 +60,24 @@
* // [optional] custom factory (an object implementing nsIFactory). If not
* // provided, the default factory is used, which returns
* // |(new MyComponent()).QueryInterface(iid)| in its createInstance().
* _xpcom_factory: { ... }
* _xpcom_factory: { ... },
*
* // [optional] an array of categories to register this component in.
* _xpcom_categories: [{
* // Each object in the array specifies the parameters to pass to
* // nsICategoryManager.addCategoryEntry(). 'true' is passed for
* // both aPersist and aReplace params.
* category: "some-category",
* // optional, defaults to the object's classDescription
* entry: "entry name",
* // optional, defaults to the object's contractID (unless
* // 'service' is specified)
* 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.
* service: true
* }],
*
* // QueryInterface implementation, e.g. using the generateQI helper
* QueryInterface: XPCOMUtils.generateQI(
@ -129,6 +146,7 @@ var XPCOMUtils = {
className: component.prototype.classDescription,
contractID: component.prototype.contractID,
factory: this._getFactory(component),
categories: component.prototype._xpcom_categories
});
}
@ -149,6 +167,7 @@ var XPCOMUtils = {
var componentCount = 0;
debug("*** registering " + fileSpec.leafName + ": [ ");
compMgr.QueryInterface(Ci.nsIComponentRegistrar);
for each (let classDesc in classes) {
debug((componentCount++ ? ", " : "") + classDesc.className);
compMgr.registerFactoryLocation(classDesc.cid,
@ -157,6 +176,17 @@ var XPCOMUtils = {
fileSpec,
location,
type);
if (classDesc.categories) {
let catMan = XPCOMUtils.categoryManager;
for each (let cat in classDesc.categories) {
let defaultValue = (cat.service ? "service," : "") +
classDesc.contractID;
catMan.addCategoryEntry(cat.category,
cat.entry || classDesc.className,
cat.value || defaultValue,
true, true);
}
}
}
if (postRegister)
@ -173,6 +203,13 @@ var XPCOMUtils = {
for each (let classDesc in classes) {
debug((componentCount++ ? ", " : "") + classDesc.className);
if (classDesc.categories) {
let catMan = XPCOMUtils.categoryManager;
for each (let cat in classDesc.categories) {
catMan.deleteCategoryEntry(cat.category,
cat.entry || classDesc.className);
}
}
compMgr.unregisterFactoryLocation(classDesc.cid, fileSpec);
}
debug(" ]\n");