基于Mozilla Thunderbird的扩展开发(七)---工欲善其事,必先利其器

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><lock aspectratio="t" v:ext="edit"></lock></shapetype>

20080506.bmp

Mozilla扩展系列链接:

1浅谈基于Mozilla Thunderbird的扩展开发

2基于Mozilla平台的扩展开发(续)----XPCOM组件篇

3基于Mozilla Thunderbird的扩展开发(三)---如何获取邮件的完整信息

4基于Mozilla Thunderbird的扩展开发(四)---修改源代码实现自动保存附件

5基于Mozilla Thunderbird的扩展开发(五)---进程间通信之Socket篇(上)

6基于Mozilla Thunderbird的扩展开发(六)---进程间通信之Socket篇(下)

7, 基于Mozilla Thunderbird的扩展开发(七)---工欲善其事,必先利其器

Mozilla最为人诟病的地方就是没有称手的开发工具,这对于我们这些被微软惯坏的开发人员来说,如果没有Visual Studio这样舒服的工具的话,谁会投入你的怀抱呢?本文就希望从三个方面介绍下我所了解到的Mozilla平台下的开发工具及一些小技巧。

最原始的方法当然是全部手工打造,从插件的编写,到打包,这样做的好处是对Mozilla平台下插件的开发有比较深入的了解,但缺点就是每次做一些小的修改后都需要重复进行压缩,打包等一系列繁杂的工序,如果你喜欢这种方法,可以参考我这篇文章:《浅谈基于Mozilla ThunderBird的扩展开发》,也可以参考Mozilla开发中心这篇文章《Building an Extension》。

每次修改代码后就得自己手动重新打包,发布,安装,你对这些已经感到厌烦了吗?好的,那就想办法脱离苦海吧。我们仔细分析后发现,就是一个打包的问题,因此我们就可以使用Ant来完成这些琐碎的打包工作,下面就是《浅谈基于Mozilla ThunderBird的扩展开发》中使用的build.xml文件:

None.gif <? xmlversion="1.0" ?>
None.gif
< project name ="helloworld" default ="createxpi" >
None.gif
< delete file ="helloworld.xpi" />
None.gif
< delete file ="helloworld.jar" />
None.gif
< target name ="createjar" >
None.gif
< zip destfile ="helloworld.jar" compress ="false" >
None.gif
< fileset dir ="chrome" >
None.gif
< include name ="content/**" />
None.gif
</ fileset >
None.gif
</ zip >
None.gif
</ target >
None.gif
None.gif
< target name ="createxpi" depends ="createjar" >
None.gif
< zip destfile ="helloworld.xpi" >
None.gif
< zipfileset dir ="." includes ="helloworld.jar" prefix ="chrome" />
None.gif
< zipfileset dir ="." includes ="chrome.manifest" />
None.gif
< zipfileset dir ="." includes ="install.rdf" />
None.gif
</ zip >
None.gif
</ target >
None.gif
</ project >
None.gif

如果你的项目结构比这个要复杂的话,请根据自己的需求更改此文件再使用Ant编译就可以了。这种方法也是我目前使用最多的方法了,因为感觉控制起来比较灵活。

如果你喜欢集成化的开发工具,想让它为你做更多的事情的话,这里推荐一个工具:NetBean+foxbeans+foxfiles,后面两个插件是用于开发Mozilla平台插件的,下载地址为:

Foxbeans: http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=4209

Foxfiles: http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=4649

官方的入门文档:

http://wiki.netbeans.org/MozillaAddonDevelopment

不过不推荐用这个插件,试用了一下,并不是很好用。

再来谈下另一个问题,在做界面时,如何快速地获知目标程序中想overlay掉的控件的id以及它的属性呢?这在做插件开发时是一个比较重要的方面,因为你的插件的界面就是附着在目标程序(firefoxthunderbirdsunbird)上的。那么官方推荐的工具就够用了,这个插件就是DOM Inspector,它可以用来定位你所需要的控件。

Venkman是官方推荐的调试工具,但个人感觉还是不大好用。

另外几个调试的技巧是:1)可以试用”dump语句来显示调试信息,不过这需要进行一些配置工作。2)在代码中使用nsIConsoleService 将日志信息输出到JavaScript控制台中。

3)自己编译一个debug版本的firefoxthunderbird,并且在其源代码或你的C++ XPCOM组件中设置断点,进一步的信息可以参考Mozilla开发中心的文档。

除此以外,我们也可以自己开发一个日志工具类来记录感兴趣的信息,下面是我常用的一个日志组件类:

None.gif constCI = Components.interfaces,CC = Components.classes,CR = Components.results;
None.giftBirdBiffUtility.classID
= Components.ID( " {e07f8540-831f-11db-9fe1-0800200c9a66} " );
None.giftBirdBiffUtility.contractID
= " @phinecos.cnblogs.com/HelloWorld/utility;1 " ;
None.giftBirdBiffUtility.classDescription
= " UtilityService " ;
None.gif
None.gif
// 日志组件
None.gif
function tBirdBiffUtility()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
this.consoleService=CC["@mozilla.org/consoleservice;1"].getService(CI.nsIConsoleService);//控制台服务
InBlock.gif
this.logFile=null;//日志文件对象
InBlock.gif
this.logToFile=true;//是否开启日志功能,默认为开启,插件发布后,关闭它就是
ExpandedBlockEnd.gif
}

None.gif
None.giftBirdBiffUtility.prototype
=
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gifinitialize:
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//初始化
InBlock.gif
this.getLoggingPref();
ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gifcloseLogFile:
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//关闭日志文件
InBlock.gif
if(this.logFile)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
this.logFile.close(null);
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gifopenLogFile:
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//打开日志文件
InBlock.gif
this.closeLogFile();//关闭先前的日志文件
InBlock.gif

InBlock.gif
if(!this.logToFile)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
return;
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
vartmpFile=CC["@mozilla.org/file/directory_service;1"]
InBlock.gif.getService(CI.nsIProperties).get(
"TmpD",CI.nsILocalFile);
InBlock.gif
//构造日志文件名称
InBlock.gif
varfilename="HelloWorld";
InBlock.gif
if(this.isFirefox())
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.giffilename
+="-firefox.log";
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
if(this.isSunbird())
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.giffilename
+="-sunbird.log";
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
if(this.isThunderbird())
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.giffilename
+="-thunderbird.log";
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.giftmpFile.append(filename);
InBlock.gif
//创建不重名的日志文件
InBlock.gif
tmpFile.createUnique(CI.nsIFile.NORMAL_FILE_TYPE,0664);
InBlock.gif
InBlock.gif
this.logFile=CC["@mozilla.org/network/file-output-stream;1"]
InBlock.gif.createInstance(CI.nsIFileOutputStream);
InBlock.gif
InBlock.gif
//write,create,truncate
InBlock.gif
this.logFile.init(tmpFile,0x02|0x08|0x20,0664,this.logFile.DEFAULT_REPLACEMENT_CHARACTER);
ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gifisFirefox:
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
if(this.getApplicationId()=="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}")
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
returntrue;
ExpandedSubBlockEnd.gif}

InBlock.gif
else
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
returnfalse;
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gifisSunbird:
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
if(this.getApplicationId()=="{718e30fb-e89b-41dd-9da7-e25a45638b28}")
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
returntrue;
ExpandedSubBlockEnd.gif}

InBlock.gif
else
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
returnfalse;
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gifisThunderbird:
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
if(this.getApplicationId()=="{3550f703-e582-4d05-9a08-453d09bdfdc6}")
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
returntrue;
ExpandedSubBlockEnd.gif}

InBlock.gif
else
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
returnfalse;
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gifgetLoggingPref:
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
//lookforanduseapreferenceifgiven
InBlock.gif
if(this.logToFile==true)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//开启了日志功能
InBlock.gif
this.openLogFile();
InBlock.gif
this.logToConsole("tBirdBiffUtility.getLoggingPref","thunderbirdbiff.logToFilepreferencesettingis"+this.logToFile);
ExpandedSubBlockEnd.gif}

InBlock.gif
else
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//没有开启日志功能
InBlock.gif
this.logToConsole("tBirdBiffUtility.logToFile","Nothunderbirdbiff.logToFilepreferencesettingfound,usingFALSEdefault");
InBlock.gif
this.logToFile=false;
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.giflogError:
function(source,message)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//记录错误信息
InBlock.gif
varcallingFunction=source;
InBlock.gif
varerror=CC["@mozilla.org/scripterror;1"].createInstance(CI.nsIScriptError);
InBlock.giferror.init(callingFunction
+"():"+message,null,null,null,null,CI.nsIScriptError.errorFlag,null);
InBlock.gif
this.consoleService.logMessage(error);
InBlock.gif
this.log(source,"ERROR-"+message);
InBlock.gif
this.callingFunction=null;
InBlock.gif
this.error=null;
ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gifwriteToLogFile:
function(msg)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//写入日志文件
InBlock.gif
if(this.logToFile)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
this.logFile.write(msg+"/n",msg.length+1);
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.giflog:
function(source,message)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//日志功能
InBlock.gif
varmsg=source+"():/n/"+message;
InBlock.gif
InBlock.gif
try
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
this.writeToLogFile(msg);
ExpandedSubBlockEnd.gif}

InBlock.gif
catch(e)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
varerrorMsg="Errortryingtowritelogfile:"+e+"--Openinganewfile/n";
InBlock.gif
this.logToConsole(errorMsg);
InBlock.gif
this.openLogFile();
InBlock.gif
if(this.logFile)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
this.writeToLogFile(errorMsg);
InBlock.gif
this.writeToLogFile(msg);
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.giferrorMsg
=null;
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gifmsg
=null;
ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.giflogToConsole:
function(source,message)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//写日志到控制台
InBlock.gif
varmsg=this.getAddonName()+"."+source+"():/n/"+message;
InBlock.gif
this.consoleService.logStringMessage(msg);
InBlock.gif
this.log(source,message);
InBlock.gifmsg
=null;
ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gifgetApplicationInfo:
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//获取目标程序信息
InBlock.gif
returnCC["@mozilla.org/xre/app-info;1"].getService(CI.nsIXULAppInfo);
ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gifgetApplicationId:
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//获取目标程序id
InBlock.gif
if(!this.id)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
this.id=this.getApplicationInfo().ID;
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
returnthis.id;
ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gifonObserve:
function(subject,topic,data)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gif
//nsISupports
InBlock.gif
QueryInterface:function(aIID)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
if(aIID.equals(CI.nsISupports)||
InBlock.gifaIID.equals(CI.nsIClassInfo)
||
InBlock.gifaIID.equals(CI.nsIObserver))
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
returnthis;
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
throwCR.NS_ERROR_NO_INTERFACE;
ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gif
//nsIClassInfo
InBlock.gif
getInterfaces:function(aCount)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
varifaces=newArray();
InBlock.gififaces.push(CI.nsISupports);
InBlock.gififaces.push(CI.nsIClassInfo);
InBlock.gififaces.push(CI.nsIObserver);
InBlock.gifaCount.value
=ifaces.length;
InBlock.gif
returnifaces;
ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gif
//nsIClassInfo
ExpandedSubBlockStart.gifContractedSubBlock.gif
getHelperForLanguage:function(aLanguage)dot.gif{returnnull;},
ExpandedSubBlockStart.gifContractedSubBlock.gifgetcontractID()
dot.gif{returntBirdBiffUtility.contractID;},
ExpandedSubBlockStart.gifContractedSubBlock.gifgetclassID()
dot.gif{returntBirdBiffUtility.classID;},
ExpandedSubBlockStart.gifContractedSubBlock.gifgetclassDescription()
dot.gif{returntBirdBiffUtility.classDescription;},
ExpandedSubBlockStart.gifContractedSubBlock.gifgetimplementationLanguage()
dot.gif{returnCI.nsIProgrammingLanguage.JAVASCRIPT;},
ExpandedSubBlockStart.gifContractedSubBlock.gifgetflags()
dot.gif{returnCI.nsIClassInfo.SINGLETON;},
InBlock.gif
InBlock.gif
//nsIObserver
InBlock.gif
observe:function(aSubject,aTopic,aData)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
switch(aTopic)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
case"xpcom-startup":
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
//thisisrunveryearly,rightafterXPCOMisinitialized,butbefore
InBlock.gif
//userprofileinformationisapplied.Registerourselvesasanobserver
InBlock.gif
//for'profile-after-change'and'quit-application'
InBlock.gif
//
InBlock.gif
varobsSvc=CC["@mozilla.org/observer-service;1"].getService(CI.nsIObserverService);
InBlock.gifobsSvc.addObserver(
this,"profile-after-change",false);
InBlock.gifobsSvc.addObserver(
this,"quit-application",false);
InBlock.gif
break;
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
case"profile-after-change":
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
//Thishappensafterprofilehasbeenloadedanduserpreferenceshavebeenread.
InBlock.gif
//startupcodehere
InBlock.gif
this.initialize();
InBlock.gif
break;
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
case"quit-application":
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
varobsSvc=CC["@mozilla.org/observer-service;1"].getService(CI.nsIObserverService);
InBlock.gifobsSvc.removeObserver(
this,"profile-after-change");
InBlock.gifobsSvc.removeObserver(
this,"quit-application");
InBlock.gif
break;
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
default:
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
this.onObserve(aSubject,aTopic,aData);
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}
,
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gifgetwrappedJSObject()
dot.gif{returnthis;}
ExpandedBlockEnd.gif}

None.gif
None.gif
// ====================================================================================
None.gif//
constructorsforobjectswewanttoXPCOMify
None.gif//
None.gif
var gXpComObjects = [tBirdBiffUtility];
None.gif
var gCatObserverName = tBirdBiffUtility.classDescription; // canbeanything
None.gif
var gCatContractID = tBirdBiffUtility.contractID;
None.gif
None.gif
// **********
None.gif//
genericregistrationcodebelow.UsefulURL:http://www.mozilla.org/projects/xpcom/book/cxc/html/weblock.html
None.gif//
**********
None.gif
function NSGetModule(compMgr,fileSpec)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gifgModule._catObserverName
=gCatObserverName;
InBlock.gifgModule._catContractId
=gCatContractID;
InBlock.gif
InBlock.gif
for(variingXpComObjects)
InBlock.gifgModule._xpComObjects[i]
=newFactoryHolder(gXpComObjects[i]);
InBlock.gif
InBlock.gif
returngModule;
ExpandedBlockEnd.gif}

None.gif
None.gif
function FactoryHolder(aObj)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
this.classID=aObj.classID;
InBlock.gif
this.contractID=aObj.contractID;
InBlock.gif
this.className=aObj.classDescription;
InBlock.gif
this.factory=
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gifcreateInstance:
function(aOuter,aIID)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
if(aOuter)
InBlock.gif
throwCR.NS_ERROR_NO_AGGREGATION;
InBlock.gif
InBlock.gif
return(newthis.constructor).QueryInterface(aIID);
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}
;
InBlock.gif
InBlock.gif
this.factory.constructor=aObj;
ExpandedBlockEnd.gif}

None.gif
None.gif
var gModule =
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif_xpComObjects:
dot.gif{},
InBlock.gif_catObserverName:
null,
InBlock.gif_catContractId:
null,
InBlock.gif
InBlock.gifregisterSelf:
function(aComponentManager,aFileSpec,aLocation,aType)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gifaComponentManager.QueryInterface(CI.nsIComponentRegistrar);
InBlock.gif
for(varkeyinthis._xpComObjects)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
varobj=this._xpComObjects[key];
InBlock.gifaComponentManager.registerFactoryLocation(obj.classID,obj.className,
InBlock.gifobj.contractID,aFileSpec,aLocation,aType);
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
varcatman=CC["@mozilla.org/categorymanager;1"].getService(CI.nsICategoryManager);
InBlock.gifcatman.addCategoryEntry(
"xpcom-startup",this._catObserverName,this._catContractId,true,true);
InBlock.gifcatman.addCategoryEntry(
"xpcom-shutdown",this._catObserverName,this._catContractId,true,true);
ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gifunregisterSelf:
function(aCompMgr,aFileSpec,aLocation)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
varcatman=CC["@mozilla.org/categorymanager;1"].getService(CI.nsICategoryManager);
InBlock.gifcatman.deleteCategoryEntry(
"xpcom-startup",this._catObserverName,true);
InBlock.gifcatman.deleteCategoryEntry(
"xpcom-shutdown",this._catObserverName,true);
InBlock.gif
InBlock.gifaComponentManager.QueryInterface(CI.nsIComponentRegistrar);
InBlock.gif
for(varkeyinthis._xpComObjects)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
varobj=this._xpComObjects[key];
InBlock.gifaComponentManager.unregisterFactoryLocation(obj.classID,aFileSpec);
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gifgetClassObject:
function(aComponentManager,aCID,aIID)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
if(!aIID.equals(CI.nsIFactory))
InBlock.gif
throwCR.NS_ERROR_NOT_IMPLEMENTED;
InBlock.gif
InBlock.gif
for(varkeyinthis._xpComObjects)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
if(aCID.equals(this._xpComObjects[key].classID))
InBlock.gif
returnthis._xpComObjects[key].factory;
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
throwCR.NS_ERROR_NO_INTERFACE;
ExpandedSubBlockEnd.gif}
,
InBlock.gif
InBlock.gifcanUnload:
function(aComponentManager)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
returntrue;
ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif
None.gif
None.gif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值