本篇逐步实现一个firefox的helloworld级别的扩展。
一、firefox扩展机制的简单介绍
firefox通过一种称为overlay的机制,将扩展所定义的xul文件与firefox原生的xul文件动态的合并,从而在firefox的界面上添加了扩展所定义的界面元素。我们可以将overlay简单的理解为动态的xml合并机制。
在firefox的官方文档中,可以被扩展的元素被称为"merge point",但是我没有找到有任何文档描述了firefox中有哪些"merge point",也没有找到"merge point"的定义标准。按照我理解,对于"merge point"比较简单的解释应该就指的是拥有并列子元素的节点,也就说,如果一个节点拥有并列的子元素,那么我们就可以认为这个节点是一个"merge point",也就可以被扩展。当然,实际上"merge point"除了新增元素,也可以修改现有元素的属性,删除现有元素,所以其真实定义应该会更复杂些。
首先,我们看一个例子,比如在firefox自己的xul文件中,定义了如下一个元素:
<itemList id="mainlist"> <item text="hello" /> <item text="welcome" /> <item text="nihao" /> </itemList >
那么,我就可以认为这个id为mainlist的itemList 节点就是一个"merge point",能够被扩展。
在扩展的xul中,我们可以这样定义:
<overlay id="extmainlist" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <itemList id="mainlist"> <item text="i am here" /> </itemList > <overlay>
那么经过overlay机制的动态合并,在运行时,我们会得到如下一个mainlist的描述:
<itemList id="mainlist" > <item text="hello" /> <item text="welcome" /> <item text="nihao" /> <item text="i am here" /> </itemList >
然后,firefox就会根据这个描述来展示最后的界面,从而将扩展的界面元素加入了firefox中。
二、创建一个扩展
a)在你的机器上随便找个地方新建个目录吧,名称随意
后面所有的操作均在此目录下。
b)新建一个名为install.rdf的文件,用于描述扩展的基本信息
内容样例如下,字段意义请参见注释。
<?xml version="1.0"?> <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> <!--扩展id,自己生成,也可以使用--> <em:id>{64D98355-2062-422D-A67F-8F175E0E519B}</em:id> <!--扩展的版本号--> <em:version>1.0</em:version> <!--扩展的类型2是Extensions,4是Themes,8是locale--> <em:type>2</em:type> <em:targetApplication> <Description> <!--FireFox的GUID,不能修改--> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!--扩展的最低版本号--> <em:minVersion>1.5</em:minVersion> <!--扩展的最高版本号--> <em:maxVersion>3.6.*</em:maxVersion> </Description> </em:targetApplication> <!--扩展的名称--> <em:name>HelloWorld</em:name> <!--扩展的描述--> <em:description>HelloWorldTestDes</em:description> <!--扩展的开发者--> <em:creator>HelloWorldCreator</em:creator> <!--扩展的主页--> <em:homepageURL>http://www.HelloWorld.com/</em:homepageURL> </Description> </RDF>
c)新建一个名为chrome.manifest文件
chome是内容区域外其他区域的界面元素的集合,描述了比如状态栏,菜单栏,标题栏等等元素。chome提供了content(内容布局)、skin(皮肤)和local(语言信息)的支持。chrome.manifest文件描述了将扩展注册到firefox的chome体系中的必要信息,也就说明了chome系统如何找到扩展相关的文件。
样例内容如下:
content helloworld chrome/content/ overlay chrome://browser/content/browser.xul chrome://helloworld/content/helloworld.xul
第一行指明了helloworld这个扩展content子系统的所在目录。chome系统将会到这个目录下寻找扩展的界面描述文件,即xul文件。第二列的"helloworld”的也就是扩展PackgeName,同时,要注意chrome://helloworld/content/helloworld.xul中的helloworld也是PackgeName,这两个地方要对应。
第二行指明了扩展将会用helloworld.xul在browser.xul中新增新的元素,当firefox加载browser.xul,会同时加载时helloworld.xul,并将两个xul中所描述的界面元素进行合并。在helloworld.xul文件中,我可以对browser.xul中定义的元素进行增删添改。overlay是firefox 的扩展机制,提供了动态合并xul的能力。
d)建立了一个chrome目录,再在chrome目录下建立一个content目录
chome是内容区域外其他区域的界面元素的集合,描述了比如状态栏,菜单栏,标题栏等等元素。chome提供了conten(内容布局)、skin(皮肤)和local(语言信息)的支持。
本次我们只涉及到content,所以只需要建立content目录。
e)在content目录下新建helloworld.xul文件
内容样例为:
<?xml version="1.0"?> <overlay id="helloworld" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <menubar id="main-menubar"> <menu id="hellowolrd-menu" label="HelloWolrd" accesskey="HelloWolrd"> <menupopup id="HelloWolrdPopup" onpopupshowing="updateEditUIVisibility()" onpopuphidden="updateEditUIVisibility()"> <menuitem id="menu_undo111" label="HelloWolrd MenuItem1" key="key_undo" accesskey="HelloWolrd213213" /> <menuitem id="menu_redo222" label="HelloWolrd MenuItem2" key="key_redo" accesskey="HelloWolrdssdsdw" /> </menupopup> </menu> </menubar> </overlay>
这里指定了扩展id为main-menubar的menubar,在这个menubar 上新增一个菜单。你可以在这里指定扩展其他的界面元素。
至此,插件的制作以及完成,下载我们看一下如何将制作好的扩展安装到firefox上。
三、扩展的安装
可以预见的是,在开发过程我们会不断修改文件和配置,然后不断的重新安装,重新加载,重新崩溃。
这可是个体力活。
就我所知,有两种方式来安装扩展,首先谈谈常规的不那么适合开发模式的那种:)
1、用XPI方式安装
将扩展相关文件(不要外层文件夹,只需要rdf所在的目录)打包成一个zip包,将这个zip包的后缀名修改为.xpi。
然后将此xpi文件拖拽到firefox上,就会自动弹出扩展安装的窗口:
2、用代理文件(Firefox extension proxy file)方式
这种方式可以指定firefox在机器上的任意目录安装扩展,无需上面那种反复打包,反复修改后最,反复拖拽,反复点击的过程。采用这种方式,修改了扩展的文件之后,配合上篇所介绍的“Reload all chrome”即可使得所有更改立即生效。
具体的做法是这样:
点击“开始 - 运行”输入 %APPDATA%/Mozilla/Firefox/profiles ,有多少个profile,在这个目录下就会有多少个子目录。如果你的开发profile名是dev,那么看到一个名为xxxxxxx.dev的目录(xxxxxxx是随机字符,未深究),如图:
那么进入xxxxxxx.dev/extensions/目录,我这里就是5g285s0o.dev/extensions/,在此目录下创建一个以扩展ID(即定义在install.rdf文件中em:id)为名的文件。
比如我的扩展ID为{64D98355-2062-422D-A67F-8F175E0E519B},那么我就创建一个以此为名的文本文件。内容输入扩展所在目录(也即install.rdf文件所在目录,全路径,末尾有“/”)。
重启firefox就会提示你安装了新的扩展。
插件显示如下: