読み込んでいます...

在Firefox开发当中我们经常会使用XPCOM与本地信息,或者与服务器的信息进行交互,从另一方面来说,XPCOM也可以让我们的程序封装的更好,不过XPCOM有点复杂。所谓XPCOM,就大概类似于IE里面的COM组件,不过Firefox里面的XPCOM可以用多种语言写,例如C++,JavaScript,Python等等,关于XPCOM可以看我原来写的一篇文章,能够快速的上手。不过如果你不了解XPCOM的话建议不要看我这篇文章,因为这篇文章毕竟不是给初学者写的,因为初学者可能很难理解XPCOM,而对于使用了XPCOM有一定程度的人,可以看看。

首先还是链接一下官方文档吧,How to Build an XPCOM Component in Javascript,如果英语不太好或者不太了解的话可以继续读下去。XPCOM呢,就是一个跨平台的组件对象模型,说简单点,就是如果C++要和Java交互,就需要一个中间的东西,来翻译这个东西,而我们大部分都是继承接口然后实现接口,达到不同语言可以互相交流的目的,XPCOM也是这样,这样就使得Firefox能够使用C++,Python等语言编写的dll了,在开发和维护上都方便了很多。

为了方便的使用XPCOM,并且和不同语言交互,我们必须定义接口,接口在Firefox里面被称为XPIDL,具体可以看这里。其中官方文档已经写的很详细了,我们可以写下面的IDL文件。

#include nsISupports.idl

[scriptable, uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)]
interface nsIHelloWorld : nsISupports
{
string hello();
};

这个就是定义了接口,然后我们就要在语言中实现我们的接口了,而我们这里只说JavaScript,所以可以不需要编写IDL文件,不过这里提到的话,就是要注意一下,其他语言需要定义

由于我们不需要IDL,就直接用JS实现一个XPCOM,我直接整体的写上来了,注释都在代码里了,如果你偷懒,你可以直接拷贝下来然后保存为JS文件,不过记得要改一下名字。

/***********************************************************
一些const变量
**********************************************************
*/

// 可以从interface里面继承过来,这里是自定义的interface,也可以不写
const nsIGuoJingTest = Components.interfaces.nsIGuoJingTest;

// 这个必须要继承nsISupport
const nsISupports = Components.interfaces.nsISupports;

// 必须要给自己的类一个唯一的GUID,这个可以从很多网站上生成了
const CLASS_ID = Components.ID({a5a64a7d-715a-43f7-beef-99ecee558014});

// 类的描述
const CLASS_NAME = My Hello World Javascript XPCOM Component;

// XPCOM的唯一的标识,通过这个来调用
const CONTRACT_ID = @www.jguoer.com/GuoJingTest;1;

/***********************************************************
定义一个类
**********************************************************
*/

//定义类的结构
function GuoJingTest() {
//获取当前的类的对象
this.wrappedJSObject = this;
}

//类的实例的实现
GuoJingTest.prototype = {

//定义一个函数
hello: function() {
return Hello World!;
},

//查看是否是继承了Interface
QueryInterface: function(aIID)
{
if (!aIID.equals(nsIGuoJingTest) &&
!aIID.equals(nsISupports))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
}
};

/***********************************************************
class factory
包装我们的类以便可以从XPCOM的class中调用
不理解可以照抄
**********************************************************
*/
var GuoJingTestFactory = {
createInstance:
function (aOuter, aIID)
{
if (aOuter != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return (new GuoJingTest()).QueryInterface(aIID);
}
};

/***********************************************************
XPCOM注册,同样不理解可以照抄
**********************************************************
*/
var GuoJingTestModule = {
registerSelf:
function(aCompMgr, aFileSpec, aLocation, aType)
{
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;
//判断ID是否相等
if (aCID.equals(CLASS_ID))
//这里可以看到是返回了我们的XPCOM的包装
return GuoJingTestFactory;

throw Components.results.NS_ERROR_NO_INTERFACE;
},

canUnload: function(aCompMgr) { return true; }
};

/***********************************************************
这个方法会在每次Firefox启动的时候Firefox自己调用
方法名,参数名基本不用变,返回刚才封装的XPCOM
的Model就可以了
**********************************************************
*/
function NSGetModule(aCompMgr, aFileSpec) { return GuoJingTestModule; }

上面我们就写完了一个XPCOM,其中除了自己定义的类的方法以外,其他的所有方法都要写,不理解可以,可以照抄,但是要写,否则不能注册XPCOM。当我们写完之后,就需要放到扩展代码根目录的components文件夹下,Firefox会认得这个。

放完之后,我们就可以写下面的代码调用自定义XPCOM了。

//通过XPCOM的ID调用XPCOM
var myComponent = Components.classes['@www.jguoer.com/GuoJingTest;1']
.getService().wrappedJSObject;
//打印相关内容
alert(myComponent);
alert(myComponent.hello());

我们可以通过XPCOM的ID调用XPCOM了,调用之后我们就可以访问自定义XPCOM的一些组件,方法了。在很多时候,我们需要继承和实现Firefox里面的接口达到更多更自由的操作目的,这个时候我们就不得不继承甚至重写XPCOM里面的内容,所以这里就需要自定义XPCOM了。

Firefox高阶的扩展开发还是比较复杂的,最近研究几个这方面的内容,着实头疼,还看了Google工具栏的代码,比较复杂,XPCOM的使用也比较麻烦,有时候XUL还需要绑定XML,这个有些复杂,我会在后面的文章提到。

366路过 2评论 Firefox Addon 阅读全文..
  1. 生活笔谈 @

    侧边栏又回来了,稀饭~~

  2. 置顶的更新 : GuoJing's Blog | 用心对待每一行代码 @

    [...] Firefox Add-on – 自定义XPCOM [...]

:-D :-? 8) :cry: 8-O :lol: :-x :-| :?: :-P :oops: :roll: :( :) :-o :wink: more »