??xml version="1.0" encoding="utf-8" standalone="yes"?> 插g写好了,下面p做一个安装包了。最好再提供更新功能Q以便在插g有更新的时候,及时通知用户q行插g更新?/p>
我们开发的时候,直接生成的dll丢到Firefox安装目录下的plugins目录可以工作了Q但是你如何说服让用h手动完成qg事情Q估计很难。因此,提供一个安装包Q可能是最好的选择。用户只需要点几下鼠标可以完成插件的安装了?/p>
不过到写q篇文章的时候,我还不清楚怎么让安装包l过Mozilla的验证,因ؓ没有l过验证的插Ӟ在安装的时候会出现“仅安装信M者的附加lg”提示对话框,提示用户仅安装受信Q作者的插g。如果有人知道怎么Lq个警告对话框,q望不吝赐教?/p>
最最单的插g安装包在q篇文章中开头处写的很清楚了Q?a title="https://developer.mozilla.org/en/Shipping_a_plugin_as_an_extension" >https://developer.mozilla.org/en/Shipping_a_plugin_as_an_extension 安装包的目录l构Q?/p>
install.rdf 其中xpt文g可选。install.rdf的内容ؓQ? <RDF xmlns=" xmlns:em="> 上面内容安装目录结构用zip格式压羃Q将后缀名改为xpiOK了?/p>
但是我们要做得事情远不止q些Q?/p>
要做的事情还很多。那么我们就一个个来研I吧?/p>
一、如何提供插件的更新自动通知Q?/strong> 关于Install manifestQ即install.rdfQ文件内容,Mozilla有篇很详l的文章Q?a title="https://developer.mozilla.org/en/Install.rdf" >https://developer.mozilla.org/en/Install.rdfQ可以进行参考?/p>
其中有个节点名称是:updateURL。用q个标签包含一个可查询更新信息的URLq接Q今后当FF在查询插件是否有更新Ӟ会到你指定的q个URL上去查询?/p>
q个URL可以是一个cgiE序、servlet、asp(x)Q也可以是一个固定的rdf文g链接。另外文章中也提C另外一U办法:如果你没有提供updateURLQFF的附加组件管理器会向addons.mozilla.org发送请求,当你上传了一个新版本的插件或者通过作者接口(author interfaceQ更改了兼容性参敎ͼ一个更新的manifest文g会被自动生。另外,MozillaupdateURL使用https而非httpQ否则你应该提供updateKeyQ可以用McCoy生成Q?/p>
那么Q负责更新的rdf怎么~写呢?你可以参考这文章:https://developer.mozilla.org/en/Extension_Versioning%2c_Update_and_Compatibility#Update_RDF_Format。由于文章中写的很清晎ͼq且提供了详l的例子代码Q这里我׃废话了?/p>
二、如何将扩展和插件捆l在一赯用户安装Q?/strong> q个很简单。之前的章节我们已经做过一个简单的Extension安装包,如果想附加一个插件的话,只需要和chrome的同U目录下新徏一个plugins目录Q然后将dll及相x件放在里面,最后一h包即可?/p>
当在FF中安装此xpiӞFF会将Extension和Plugin解压到FF的Profiles目录下。插件和扩展卛_生效?/p>
注意q里与我们之前将插gdll攑֜FF安装目录下的plugins目录下有些不同(臛_位置不同Q,FF同样能够正确地识别我们的插g。另外Mozilla也推荐做成安装包Q这P在用户卸载组件的时候,可以同时Extension和Plugin都卸载掉?/p>
三、如何对插gq行{Q?/strong> 很抱歉,q没扑ֈ{案…… 四?如何发布你的插g和扩展,以便让更多h知晓Q?/strong> 首先需要在Mozilla|站上注册一个̎P需要提供合法E-mailQ因Ȁz)?/p>
d后,在Mozilla 附加lg首页上你会看C?#8220;开发者工?#8221;的链接。进入后Q会有明昄D链接Q如“提交附加lg”。通过q个面Q按照向|你就可以你的插件发布出来了。剩下的事,是宣传咯,呵呵?/p>
OKQ《我的Firefox插g开发之旅》系列文章就先到q里。将来我也许q会写一些关于编写FF的Extension和Plugin斚w的技术细节文章。看心情吧,呵呵?/p> OKQ步入正题。这一节我来单说一下如何ؓ插gd和脚本语aQ如JavascriptQ交互的能力。我会ؓ插gd几个函数Q供Javascript调用?/p>
前面我们提到q浏览器调用插g的方法的序Q基本上为:NP_GetEntryPoints、NP_Initialize、NPP_New、NPP_SetWindow、NPP_GetValue。在NPP_New中,我们需要创建插件对象的实例QNPP_SetWindow中,览器会传入插gH口的信息,最后一个NPP_GetValueQ是览器来获取一些插件信息的。NPP_GetValue函数的结构是q样的: NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value); 览器会传入NPPVpluginScriptableNPObjectQ作为variable参数Q来查询插g是否支持Scriptable功能Q即和脚本语a交互的功能)Q在q里Q我们可以利用NPN_CreateObjectҎ来创Z个NPObject对象Qƈ且作为valueq回l浏览器。这P览器就通过q个NPObject对象和我们的插g建立了连接。当面上Javascript调用了我们插件对象的某个ҎӞ览器会调用该NPObject对象的HasMethodҎ来查询是否支持这个方法,如果支持Q则会调用NPObject对象的InvokeҎQ传入方法名、参数等信息。这P我们可以让|页上的脚本语言来执行我们编写的函数了。在Windows上,我们~写的函数就如同~写普通的应用E序一P可以使用很多Windows API来完成许多复杂的工作?/strong> 上面有个问题Q如何创建我们自qNPObject对象QNPN_CreateObjectҎ如何使用Q好在Mozillal我们提供了npruntimeq个例子E序Q可以让我们得以参考?/p>
先来看看NPN_CreateObjectҎ的定义: NPObject *NPN_CreateObject(NPP npp, NPClass *aClass); 关键在第二个参数上,我们需要提供一个NPClass指针。npruntime例子E序中是q么做的Q?/p>
定义了一个宏DECLARE_NPOBJECT_CLASS_WITH_BASEQ其作用是定义了一个静态的NPClass对象Qƈ且NPClass要求的所有基ҎQ都׃个ScriptablePluginObjectBasecL提供。我们根据需要,来创Z同的l承于ScriptablePluginObjectBase的类Q比如支持方法的cd支持属性的c)Q传lDECLARE_NPOBJECT_CLASS_WITH_BASE宏,q样Q当览器管我们“?#8221;的时候,我们可以按照它的需?#8220;l?#8221;它对应的对象?/p>
npruntime例子中,ScriptablePluginObject是用来处理方法的Q而ConstructablePluginObject是用来处理属性的?/p>
如何定义一个方法(或属性)Q?/strong> 1、添加一个方法(或属性)很简单,先定义一个静态NPIdentifiercd的变量,例如Q?/p>
static NPIdentifier s_idSetArgs; 2、在插g对象构造函CQ用NPN_GetStringIdentifierҎ来设|该Ҏ的名Uͼ例如Q?/p>
s_idSetArgs = NPN_GetStringIdentifier("SetArgs"); 其中QSetArgs是我们提供l脚本语a调用的方法名U?/p>
3、在ScriptablePluginObject的HasMethodҎ中,判断传入的方法名Q?/p>
bool ScriptablePluginObject::HasMethod(NPIdentifier name) return false; 4、在ScriptablePluginObject的InvokeҎ中,判断如果传入的方法名U等于我们定义的Ҏ名,则做你想要做得事情: ////////////////////////////////////////////////////////////////////////// bool ScriptablePluginObject::Invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result) { { q里做你惌做得事情 return PR_TRUE; } return PR_FALSE; } 关于Ҏ参数的接Ӟq里举个例子。比如网上q么调用Q?/p>
embedobj.SetArgs("name", "value"); 在我们的Ҏ中,可以这么接Ӟ if(args != NULL && argCount >= 2) if(npsName.utf8characters && strlen(npsName.utf8characters) > 0) //限定条gQ可以根据需要进行修攏V这里限定第一个参数内容不能ؓI?br> { PARAMPAIR paramPair; strcpy(paramPair.pName, npsName.utf8characters); //参数内存存储到我们熟悉的C m_vecParamPair.push_back(paramPair); 上面的代码中QPARAMPAIR是一个简单的l构体: typedef struct tagPARAMPAIR m_vecParamPair是一个vectorQvector<PARAMPAIR> m_vecParamPair; Z说一句,上面只是代码片段Q关于内存释放、vector清空{操作,׃不是q里要说的关键部分,所以没有列出?/p>
OKQ现在我们的插g已经可以利和网进行交互工作了?/p> 新徏了一个名为npgnet的工E,按照npruntime例子Q新Znp_entry.cpp、npn_gate.cpp、npp_gate.cpp、npgnet.def四个文gQ然后新Z一个类CGnetFFPluginQƈ且把例子中的关键代码d了进来(我删除了一些cplugincM的函数实体代码,因ؓ我实现的功能和例子中的无养I。编译后Q将生成的npgnet.dll攑ֈFF的plugins目录下,然后在地址栏键入about:pluginsQ我靠,竟然没有我的插gQ怎么回事Q三个导出函数我都按照标准写了啊Q比较了一下文Ӟ我的工程没有d.rc和resource.hQ可能是q个原因?/p>
回到VS 2005Q在资源面板d了一个VERSION资源,修改ProductName{资源项以后Q和npruntime例子比较了一下,q差MIMEType。这个东东很重要Q这个给我的感觉是FF插g的n份证QFF是靠这个东东来匚w和识别你的插件的。但是我不知道VS 2005中怎么d一个VERSION的键|所以我只好用EditPlus打开npgnet.rcQ手动添加了MIMETypeQapplication/mozilla-npgnet-scriptable-plugin。OKQ现?rc和resource.h都欧了,再编译,生成的npgnet.dll攑ֈFF的plugins目录下,然后在地址栏键入about:pluginsQ我靠,竟然q是没有我的插gQ真费解啊! 头大……接下来我q行了一pd的代码比较和试Q失败了N多次Q这里就省略不说了。最后发现原因原来在q个.rc上面。我的这?rc是在VS 2005中用菜单命令添加的Q默认语a是简体中文,而npruntime例子是英文,用文件比较工h较了一下,codepage和部分代码的位置都不太一栗其实只要把npruntime的这?rc文g替换我的q个Q然后编译输出的dllQFF可以识别了Q究竟是什么原因呢Q是我的.rc~少了些什么东西?q是FF只能识别英文?rcQ先不打研I么多了,臛_我的插g的关键点不在q个上面Q后面我q有很多事情需要去做。只要能让FF认出来,那就好?/p>
既然军_要写插gQ就要先理解插g的概念,在这个页面上有很详细的介l:https://developer.mozilla.org/en/Gecko_Plugin_API_Reference/Plug-in_Basics 下面的文字是我的一些阅ȝ记和体会Q?/p>
一、插件的加蝲q程 当一个页面打开Ӟ如果该页面上有嵌入一个插Ӟ览器将会做以下事情Q?/p>
插g可以在一个页面上被实例多个对象,也可以在同一时刻在不同的H口中被实例化。当面被关闭时Q插件的实例׃被销毁。当最后一个实例被删除后,插g代码׃从内存中被卸载掉?/p>
下面是插件内的函数调用过E: 二、插件检?/strong> 可以使用Javascript来检一个插件是不是已经安装了,下面是测试代码: 嗯,看到q里Q觉得这个检很有用。当用户尚未安装时Q可以指导用户到哪哪哪去下蝲安装Q{向一个漂亮点儿的面Q,当检已l安装了Q就动态加载插件代码。不错。:Q?/p>
三、插件结构概q?/strong> 一个插件中的方法分为插件方法(Plug-in MethodsQ和览器方法(Browser MethodsQ。插件方法是你在插g中自己去执行的那些方法,以NPP为前~命名。浏览器Ҏ是被Gecko所执行的那些方法,以NPN为前~命名。数据结构(Data StructuresQ以NP开头?/p>
插g可分为有H口和无H口两种Q不q文章中使用有窗口的Q说q样会更E_和易于控制。另外文中提C可以插件作为页面的一部分Qƈ且可以用HTML代码来控制插件的昄与否?br> <object data="audiplay.aiff" type="audio/x-aiff" class="hiddenObject"></object>
接下来文中介l了objectq个标签的用。ƈ且给了一个例子来说明ActiveX和插件如何融Z体来使用?/p>
最后面的部分是对object和embed两种标签的各U属性的说明和D例?/p>
值得一提的是,对于object和embed两种标签都可以在面上嵌入一个插件。如何取舍呢Q文章中有这么一D话Q?/p>
Though the 意思是_管object是推荐用的调用插g的方式,embed也可嵌入插gQNetscape 4.x以上的浏览器Q,但如果你惛_用户没有安装插gӞ提示他进行安装,那么应该选择用embedQ因为FF的默认插件系l仅仅在你用embed标签的时候,才会自动帮助你完成这U提C用户安装的效果?/p>
我看q以后的感觉是,object使用hg比embed要复杂,L针对FFq个览器是q样Q虽然他是HTML W3C的标准。多数情况下使用embed可以了Q何늎在谁q在用Netscape 4.x以下版本的浏览器啊,您说是不是?Q) OKQ通过q几天的学习Q终于对FF的插件编写有了一个初步的感性认识。到目前Z一切还比较利?/p> 及时修正了下一步的研究计划Q那么就让我们先来编译和试Mozilla提供的一个小例子吧。原文连接在q里Q?/p>
https://developer.mozilla.org/En/Compiling_The_npruntime_Sample_Plugin_in_Visual_Studio。文章中是以VS2003举例Q我q里以VC6来进行测试,q且步骤中需要注意的地方特别说明了一下?/p>
1、先到这里下载相x码:http://mxr.mozilla.org/seamonkey/source/modules/plugin/samples/npruntime/。不知道Z么Mozilla只提供了面形式Q没有打个包Q害得我得一个个文g下蝲和保存,郁闷?/p>
2、在VC6中新Z个Win32 Dynamic-Link Library工程Q取?#8220;nprt”。注意:工程以小写np开_q且长度不超q?个字W,q样以后׃省事很多?/p>
3、下一步,选择“An empty DLL project”Q然?#8220;Finish”?/p>
4、将刚才下蝲的源码添加到工程中来。test.html不用dQnprt.def也添加进来?/p>
5、现在还不能~译Q否则会出很多错误。打开Project SettingsQ{到C/C++标签,在Category中选择PreprocessorQ在Preprocessor Definitions中最后面dQ?XP_WIN32,MOZILLA_STRICT_API,XPCOM_GLUE,XP_WIN,_X86_。注Q如果你使用VS 2005Q需要添加全部的定义QWIN32;_WINDOWS;NPRT_EXPORTS;XP_WIN32;MOZILLA_STRICT_API;XPCOM_GLUE;XP_WIN;_X86_ 6、在Additional include directories下面dXULRunner SDK的include路径Q可以是l对路径Q也可以是相对\径,看你当初怎么解压的了。例如:..\..\xulrunner-sdk\include 7、在Category中选择Precompiled HeadersQ选择Not using precompiled headersQOKQ关闭Project Settings对话框。打开npp_gate.cppQ将下面的代码注释掉Q?br>jref NPP_GetJavaClass (void) 8、编译!……我靠Q有错:Fatal error C1083: Cannot open include file: 'npapi.h': No such file or directory。我可是严格按照教程上面写的d得啊?/p>
9、在xulrunner-sdk目录下搜索了一下npapi.hQ原来在xulrunner-sdk\sdk\include下面Q这好办Q多加一条包含\径不欧了?仿照W?步,d该目录; 10、编译!OKQ过了?/p>
11、到输出目录下将nprt.dll复制到FF安装目录的plugins目录下,例如QC:\Program Files\Mozilla Firefox\plugins\ 12、如果此时FF开着也没关系Q不用关Q这点很不错Q。在地址栏键入about:pluginsQ看看是不是有一个npruntime scriptable example pluginQ如果有Q那pC欧了,FF认出了我们的插gQ?/p>
13、在FF中打开test.htmlQ嗯Q怎么q提C安装缺失插Ӟ用EditPlus打开test.htmlQ噢Q原来有q么一句:<embed type="application/x-java-mozilla-npruntime-scriptable-plugin" style="display: block; width: 50%; height: 100px;">。因为我们刚才没有添加名字ؓx-java-mozilla-npruntime-scriptable-plugin的插Ӟ所以当然认不出来啦?/p>
14、随便点一下页面上的按钮,看看单的交互行ؓ?/p>
OKQ第一个例子还顺利,比想象中的要利。下面就该研I一下代码了Q看看FF的插件和ActiveX的区别到底有多大?/p>
附一些参考资料: 在Mozilla|站上看刎ͼ可以自己~写Component来完成一些自定义操作。需要首先安装Gecko SDKQ现在叫XULRunner SDKQ,Windows上有两个版本Q?.8是for FF1.5/2.0的,1.9是for FF3.0的,׃我机器上安装的是FF3.0Q那么就先下?.9吧,与FF1.5/2.0兼容的问题以后再说?/p>
下蝲了XULRunner SDK 1.9Q解压到本地后,在环境变量里配置了PATH到xulrunner-sdk的bin目录Q以便可以在command prompt下直接运行xulrunner.exe。OKQ环境配|完毕,下面来个写个例子吧。Mozilla提供了一个短精悍的例子E序Q在q里Q?a title="https://developer.mozilla.org/en/Getting_started_with_XULRunner" >https://developer.mozilla.org/en/Getting_started_with_XULRunner q篇文章一步一步教我们~写一个HelloWorldE序Q写的很清楚。不q做完这个例子,我有几个疑问Q?br>1、在上一节我们写的Extension中,chrome.manifestq个文g是放在根目录的(与chrome目录同Q,Z么这里把它放在了chrome目录里面呢?能否保持和Extension相同Q我单尝试了一下,q修改了chrome.manifest里面content所指向的目录,然后q行了一下,什么都没发生,没有看到正常q行时所弹出的对话框Q看来还是解析不正确Q是不是xulrunner必须要求chrome.manifest在chrome目录下面呢? 另外q里需要特别说明一点:在运行xulrunnerL行application.iniӞ千万不能丢掉.exeQ即不能?>xulrunner application.iniQ必L/>xulrunner.exe application.iniQ否则会弹出couldn't parse的错误提C,具体是什么原因我也不清楚?/p>
另外Q这里还有一关于xulrunner的教E,解释了一些概忉|的东西Q?a title="http://blogs.acceleration.net/ryan/archive/2005/05/06/1073.aspx" >http://blogs.acceleration.net/ryan/archive/2005/05/06/1073.aspx 写完q个例子Q感觉方向好像不太对Qxulrunner好像主要q是做界面,怎么做组件呢Q怎么讉K本地盘文g、甚至系l注册表Q在Mozilla的开发者页面上又看C个东东:XPCOMQ开头的一D介l文字是q样的: XPCOM is a cross platform component object model, similar to Microsoft COM. It has multiple language bindings, letting the XPCOM components be used and implemented in JavaScript, Java, and Python in addition to C++. Interfaces in XPCOM are defined in a dialect of IDL called XPIDL. XPCOM itself provides a set of core components and classes, e.g. file and memory management, threads, basic data structures (strings, arrays, variants), etc. The majority of XPCOM components is not part of this core set and is provided by other parts of the platform (e.g. Gecko or Necko) or by an application or even by an extension. 大概的意思是说XPCOMcM于微软的COMlg概念Q它可以定义一些接口,可以在JS、Java、Python以及C++中用。哈哈,看来q个才是我想要的东西。OKQ那接下来我来研究一下这个东东吧。下一节争取能完成我一开始提到的功能?/p>
plugins/
pluginlib.dll
plugintypes.xpt
<Description about="urn:mozilla:install-manifest">
<em:id>mypluginid@myplugin.com</em:id>
<em:name>My Plugin</em:name>
<em:version>1.0</em:version>
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>1.5</em:minVersion>
<em:maxVersion>3.0.*</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>
{
if(name == s_idSetArgs)
{
printf("method name = SetArgs\n");
return true;
}
}
///
/// @brief 如果某个Ҏ支持Q用HasMethod)Q当面上Javascript代码调用该方法时Q会执行本函?br>///
/// @param [in] name Ҏ?br>/// @param [in] args 参数|数组Q?br>/// @param [in] argCount 参数个数
/// @param [in] result 执行后返回给调用者的l果
///
/// @return PR_TRUE表示执行成功QPR_FALSE表示p|
///
//////////////////////////////////////////////////////////////////////////
if(name == s_idSetArgs)
{
NPVariant npvName = args[0]; //W一个参?br> NPVariant npvValue = args[1]; //W二个参?br> if(NPVARIANT_IS_STRING(npvName) && NPVARIANT_IS_STRING(npvValue)) //如果两者都是字W串cdQ当然你q可以判断是否是其他cdQ?br> {
NPString npsName = NPVARIANT_TO_STRING(npvName); //转成NPString
NPString npsValue = NPVARIANT_TO_STRING(npvValue);
int nLenName = strlen(npsName.utf8characters) + 1;
int nLenValue = strlen(npsValue.utf8characters) + 1;
paramPair.pName = new char[nLenName];
memset(paramPair.pName, 0, nLenName);
paramPair.pValue = new char[nLenValue];
memset(paramPair.pValue, 0, nLenValue);
strcpy(paramPair.pValue, npsValue.utf8characters);
}
}
}
{
LPTSTR pName;
LPTSTR pValue;
}PARAMPAIR, *PPARAMPAIR;
function DetectFFPlugin()
{
var mimetype = navigator.mimeTypes["application/mozilla-npgnet-scriptable-plugin"];
if(mimetype)
{
var plugin = mimetype.enabledPlugin;
if(plugin)
{
document.writeln("Plugin had been installed and be enabled.");
}
}
else
{
document.writeln("Sorry, Plugin has NOT been installed.");
}
}
有两U方式可以一个插件不可见Q?br>
1、如果你使用embed标签Q可以用其hidden属性,例如Q?lt;embed src="audiplay.aiff" type="audio/x-aiff" hidden="true">
2、如果你是用object标签Q由于它没有hidden属性,你可以用CSS来完成隐藏:
object
{
visibility: visible;
}
object.hiddenObject
{
visibility: hidden !important;
width: 0px !important;
height: 0px !important;
margin: 0px !important;
padding: 0px !important;
border-style: none !important;
border-width: 0px !important;
max-width: 0px !important;
max-height: 0px !important;
}
object
element is the preferred way to invoke plug-ins, the embed
element can be used for backward compatibility with Netscape 4.x browsers, and in cases where you specifically want to prompt the user to install a plug-in, because the default plug-in is only automatically invoked when you use the embed
element.
{
return NULL;
}
http://xinsync.xju.edu.cn/index.php/archives/2124
http://mqjing.blogspot.com/2008/09/plugin-firefox-plugin.html
]]>
2、application.ini中App节的IDQ和Extension的IDQ通常是一个GUIDQ有无关联呢Q?br>3、调用xulrunner.exe以后Q会产生两个目录Qextensions和updatesQ这两个目录是干什么用的呢Q?/p>
单知道了XULQ迫不及待地想立即编写一个插Ӟ哪怕什么事情都不做也好。O(∩_∩)O
通过q个面https://developer.mozilla.org/en/Building_an_ExtensionQ可以找到编写一个插件必要做得一些事情,写的很清楚。最后生的目录和文件结构是q个样子Q?br>install.rdf
chrome.manifest
chrome
|--content
|--overlay.xul Q我准备在这里编写代码,在FF的工h上添加一个按钮)
|--locale
|--en-US
|--sample.dtd
|--zh-CN
|--sample.dtd
|--zh-TW
|--sample.dtd
|--skin
|--classic
|--sampleicon.png
|--smallicon.png
|--default.css Q界面显C的样式表,今后可能会用刎ͼ
上面文g中的install.rdf、chrome.manifest基本上用例子中的好了,dtd文g里面是界面文字,q个可以模仿其他插g~写?br>overlay.xul我准备添加一D代码,用来在FF工具栏上d一个按钮。skin下面的png是准备在工具栏上d的按钮的图标?/p>
OKQ把上面整个目录用zip打个包,改后~名ؓxpiQ拖攑ֈFF3中,提示未验证作者、是否l安装。这个先不管它,以后再研I。安装以后,重启FF3Q哈哈,写的W一个Extension成功安装了!只不qoverlay.xul里面什么都没写Q所以还没有视觉上的成就感。下面开始添加overlay.xul中的代码?/p>
怎么在工h上添加按钮呢Q感谢Mozilla提供的文档,专门有一文章是讲这个地Q?a title="https://developer.mozilla.org/en/Creating_toolbar_buttons" >https://developer.mozilla.org/en/Creating_toolbar_buttons。文章里面讲的非常清楚,我这里就不废话了。不q有两点需要注意一下:
1、样式表中的ID和toolbarbutton的id一定要保持一_
2、按钮的label和tooltiptext可以直接d文字Q但如果使用了中文,有可能会昄qQ至在我的FF3上是q样Q;
3、按钮的图标一定要大小两种Q?4x24?6x16Q都提供Q?br>4、label和tooltiptext可以使用dtd中定义的文字Q但必须注意Qdtd文g必须存ؓUTF-8~码Q否则会D按钮昄不出来!
在FF3的定制工h中,有图标,但下Ҏ有文字,好像是我哪里忘记d文字了,一会儿看看?#8230;…
好了Q我的第一个FF插g写好了Q不q现在只是在工具栏上d了一个按钮而已Q什么事情都没做Q下一ơ我们添加一些行为给它?/p>
以下附上几个关键文g的内容:
<?xml version="1.0"?>
<RDF xmlns=" xmlns:em=">
<Description about="urn:mozilla:install-manifest">
<em:id>{859606AC-AFFE-4691-82C5-FA0148A7E2D4}</em:id>
<em:version>1.0</em:version>
<em:type>2</em:type>
<em:name>MeetMePlus</em:name>
<em:description>Anywhere, anytime to starting a conferencing</em:description>
<em:creator>G-NET</em:creator>
<em:iconURL>chrome://meetmeplus/skin/gnet_32.png</em:iconURL>
<em:homepageURL>http://www.meetmeplus.com/</em:homepageURL>
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>1.5</em:minVersion>
<em:maxVersion>3.0.*</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>
overlay chrome://browser/content/browser.xul chrome://meetmeplus/content/overlay.xul
content meetmeplus chrome/content/
style chrome://global/content/customizeToolbar.xul chrome://meetmeplus/skin/default.css
skin meetmeplus classic/1.0 chrome/skin/classic/
locale meetmeplus zh-CN chrome/locale/zh-CN/
<?xml version="1.0"?>
<!DOCTYPE overlay SYSTEM "chrome://meetmeplus/locale/overlay.dtd">
<?xml-stylesheet href="chrome://meetmeplus/skin/default.css" type="text/css"?>
<!ENTITY mmp.gotohome "讉KG-NET MeetMePlus">
<!ENTITY mmp.gotohome.tooltip "讉KG-NET MeetMePlus|站">
<!ENTITY mmp.option "选项">
<!ENTITY mmp.option.tooltip "自定义G-NET MeetMePlus的工作方?>
看完后,了解了XUL原来是一个支持多UWEB技术的、基于XML的界面开发语a。它既可以在q程执行Q也可以安装到本地执行?/p>
在XUL中内|了很多界面元素Q如菜单、按钮、分늭{,q样׃需要自q写很多JS来维护和控制很多界面元素了。而且Q这些界面是按照当时的OS外观来展现的Q比如同一个按钮,在MacOS上和Windows上看h׃一栗另外XUL也允许自׃用JS和CSS来定制自q个性化界面。M一句话QXUL的主要作用就是用来展现Extension的用户交互界面的?/p>
OKQ知道了XUL是什么以后,那么怎么学习它的用法呢?文章最下方适时地给Z一个连接:begin the XUL tutorialQ还Zh性化:) 我点~~~
教程很多Q很强大。看来一时半会儿全搞清楚是不可能的了。慢慢来吧?/p>
哦对了,q发C个在U的XUL~辑器,把XUL代码_进去,下面可以实时地显C界面。不q不能引用外部脚本,否则出错。链接是Q?a title="http://ted.mielczarek.org/code/mozilla/xuledit/xuledit.xul" >http://ted.mielczarek.org/code/mozilla/xuledit/xuledit.xul?/p>
先写q些Q准备开始阅读XUL教程?#8230;…
以前在IE中是使用一个ActiveX来实现的。FF的插件从来没有做q,不知道将来会遇到多少困难?/p>
在网上发C个页面:http://ted.mielczarek.org/code/mozilla/extensionwiz/Q它提供了一个FF扩展的生成向|填写完必要信息后Q会生成一个zip文g。之后我改名为xpi后,丢到我的FF 3.0中,提示不正的安装包。看来这个向导针对FF3q有些问题。具体问题是什么?现在q不清楚。让我来l箋L资料……
在Mozilla|站上了解到QFF的Extension和Plugin是两U概늚东西Q?/p>
Extension是一个zip包,里面有规定的一些必要文件。这个可以下载几个插件看一下他们的目录l构好了。我下蝲了一?QuickNoteQ看了一下,主要包括一个install.rdfQ安装包相关信息和文件资源\径等配置Q、chrome.manifestQ设|各UXUL文g路径以及其他的一些资源文件\径)、chrome文g夹(里面攄插g的所有源文gQ,不过chrome文g多w面的文g我还没有q多研究?/p>
Plugin好像是另外一码事了,在Mozilla Developer Center的Plugin开发介l文中有q么一句:Plugins are different from extensions, which modify or enhance the functionality of the browser itself. Plugins are also different from search plugins, which plug additional search engines in the search bar. Q插件与扩展不同Q它更改或者改善了览器自w的功能。插件与搜烦插g又不同,搜烦插g在搜索工h上添加了额外的搜索引擎。)
我的理解Q插件可以让你在FF中用自qView来展C、用自己~写的二q制文g来做某些事情Q不仅仅是利用FF自n支持的一些特性和功能。而扩展相Ҏ说就不需要这些东西,只利用FF的开发API好了?/p>
q样看来Q要实现我开始提到的需求,g可以开发一个Extension可以了。Foxmarks Bookmark SynchronizerQFBSQ也差不多是我的需求这U感觉:本地某些数据上传至服务器,从服务器同步下蝲一些数据到本地。FBS既然是一个扩展能够实玎ͼ那么看来我暂时不用研IPlugin了,呵呵?/p>
OKQ有了大概的目标。下面开始制订学习计划!
通过研究别h写的ExtensionQ里面有很多js、css、images、htmlQ这些应该还好理解,但是多了一些后~名ؓxul的文件。这是什么东西?看来惛_发ExtensionQ这个文仉要好好研I一下?/p>
因此Q我的第一个学习计划就是搞清楚XUL是什么,什么地方要用XULQ以及怎么写XULQ?/p>
先说到这里,下一节我来写一些XUL的学习历E?/p>