在Gecko2.0中XPCOM发生了一些变化从而影响了其兼容性,这篇文章详述这些变化,同时为升级你的代码提供一些建议。
1、不在拥有不变的接口(frozen interface)
这里不在拥有任何不变的接口,从现在开始,所有的接口都可能发生变化。文档将会被更新,允许删除对“frozen”和“unfrozen”接口的引用。
2、组件注册
在Gecko2.0中XPCOM组件注册的方式发生了改变。在Gecko2.0以前,组件注册过程中,所有的二进制组件和javascript组件都会被加载和调用,要求它们自己去注册自己。如果你使用XPCOMUtils.jsm,这个过程对你来说被隐藏了,但事实上它还存在。
然而从Gecko2.0开始,组件注册使用manifest文件,类似于chrome注册。实际上,同样的chrome.manifest文件也用来注册组件。
所有已有的XPCOM组件都需要升级来支持这点。不管怎样,这个很容易实现,而且你能同时支持这两种注册类型以实现向后兼容。
3、Component manifest
所有组件注册现在都是通过manifest文件来处理。对于扩展,和现在注册chrome使用的是一样的chrome.manifest文件。
3.1、XPT文件
任何XPT文件的路径都必须显式用interfaces的标示列在manifest文件中:
interfaces components/mycomponent.xpt
3.2、Javascript 组件
Javascript 组件的注册信息不再放在组件内部,相反放在manifest文件。组件只有当XPCOM组件管理器需要创建组件的时候才会被加载。
chrome.manifest
# The {classID} here must match the classID in mycomponent.js
component {e6b866e3-41b2-4f05-a4d2-3d4bde0f7ef8} components/mycomponent.js
contract @foobar/mycomponent;1 {e6b866e3-41b2-4f05-a4d2-3d4bde0f7ef8}
category profile-after-change MyComponent @foobar/mycomponent;1
JavaScript代码不再导出NSGetModule()函数,现在它需要导出NSGetFactory()函数,这个函数接受CID作为参数。
例如,在你的组件中javascript代码:
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
function myComponent() {
}
myComponent.prototype = {
// this must match whatever is in chrome.manifest!
classID: Components.ID("{e6b866e3-41b2-4f05-a4d2-3d4bde0f7ef8}"),
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIMyComponent]),
/* nsIMyComponent implementation goes here */
...
};
// The following line is what XPCOM uses to create components. Each component prototype
// must have a .classID which is used to create it.
const NSGetFactory = XPCOMUtils.generateNSGetFactory([myComponent]);
组件通过动态检测XPCOMUtils.jsm导出的符号来实现向后兼容Gecko1.9.2,并且导出正确的函数:
/**
* XPCOMUtils.generateNSGetFactory was introduced in Mozilla 2 (Firefox 4, SeaMonkey 2.1).
* XPCOMUtils.generateNSGetModule was introduced in Mozilla 1.9 (Firefox 3.0).
*/
if (XPCOMUtils.generateNSGetFactory)
var NSGetFactory = XPCOMUtils.generateNSGetFactory([myComponent]);
else
var NSGetModule = XPCOMUtils.generateNSGetModule([myComponent]);
3.3、二进制组件
二进制组件必须显式的用binary-component标识列在manifest文件中
binary-component components/mycomponent.dll
C++组件必须改变:二进制组件不再导出NSGetModule()函数,相反,它导出一个指向mozilla::Module结构的NSModule数据符号,关于mozilla:module结构的更多信息,看Module.h文件,对于最新的动态模块实例,看nsSampleModule.cpp。
注意nsIGenericFactory.h已经被移除,对nsIGenericFactory.h的引用应该被替换成mozilla/ModuleUtils.h。
通过使用额外的宏定义NS_IMPL_MOZILLA192_NSGETMODULE使二进制组件兼容Gecko1.9.2和mozilla 2.0成为可能,详细看nsSampleModule.cpp
注意:从Firefox4开始,针对每一个Firefox主要发行版二进制XPCOM组件必须被重新编译。如果你使用js-ctypes开发你会觉得更简单些。
同时使用二进制的扩展现在必须在install.manifest中使用unpack属性。
原文地址:https://developer.mozilla.org/en-US/docs/Mozilla/XPCOM/XPCOM_changes_in_Gecko_2.0