⼀步⼀步学习Firefox扩展的开发(1)——制作⼯具栏按钮及右键菜单Firefox提供开放、强⼤且灵活的扩展机制,因此衍⽣出了⼤量功能丰富的扩展组件,这些扩展
组件甚⾄可以说是某些⽤户爱上firefox的主要因素。
⽐较可惜的是firefox扩展开发的中⽂资料相对⽐较少,因此在这⾥我会从简单到深⼊介绍开发
firefox扩展的⼀些技术及常遇到的问题。
本⽂主要内容:
制作⼀个包含⼯具栏按钮及右键菜单的简单组件解决扩展安装后⼯具栏按钮却不显⽰的问
题
因为这个组件不需要设计交互窗⼝,因此开发过程相对简单,下⾯是这个组件运⾏的效果图:
在开始之前先介绍⼀下⼏个⽹址:
/en/Extensions官⽅开发⽹,类似MSDN,是开发时的主要参考资
料;
/en/Building_an_Extension,官⽅的⼀个基础教程,笔者通过此篇
⽂章⽽⼊门;
/code/mozilla/extensionwiz/,⼀个在线的创建扩展的向导,如果你想⽴
即创建⼀个属于⾃⼰的扩展,可以试试⽤这个向导制作⼀个雏形,然后再⾃⼰慢慢添砖添⽡。
本⽂所讲的例⼦也是⽤这个向导制作出来的。
好了,下⾯就开始讲解本⽂的⽰例组件:uusharedemo1的制作过程。
1、了解扩展组件的构成
Firefox扩展组件是以⼀个xpi⽂件的形式发布的,⽽xpi⽂件实际上是zip压缩包⽂件,我们只要
把Firefox扩展组件下载回来(⽤右键另存为即可下载),把⽂件扩展名改为zip即可解压并看到
所有的源代码,有时可能还会在压缩包⾥⾯看到jar格式⽂件,这个也是zip压缩包,改名解压即
可看到源代码。因此多下载优秀的扩展回来慢慢研究其源代码也不失为⼀种快速的学习⽅法。
⼀般xpi⽂件内部有(但不⼀定都有)如下⽬录及⽂件:
其中 uusharedemo1 为本⽂⽰例组件的名称,可以看到压缩包⾸层有:install.rdf及chrome.manifest两个⽂件以及⼀个chrome⽬录。
install.rdf:是该组件的安装信息,例如组件的名称、版本、作者等信息,XML格式;chrome.manifest:是⽤于描述该组件由哪些⽂件组成的,即⼀个资源列表;
在chrome⽬录⾥就是该组件的主要内容了,⼀般有:content、defaults、locale、skin等⽬录,它们的作⽤如下:
content:这个是最主要的⽬录,包含组件的界⾯定义以及程序代码,其中xul⽂件是界⾯定义⽂件,类似SilverLight的XAML⽂件,同样是XML格式;js⽂件是组件功能实现的代码,全部⽤javascript实现的。 skin:存放css样式表⽂件及资源位图,css是⽤来控制组件界⾯外观的。locale:如果想让组件能够在不同语⾔的firefox⾥显⽰正确的⽂本,则将不⽤的语⾔列表放到此⽬录,firefox会⾃动加载合适的语⾔⽂件。这点有些类似Win32PE可执⾏程序中的资源⽂件。defaults:存放⼀些默认值,⼀般不要此⽬录也可以;
我们可以把Firefox程序认为是⼀个平台,⽽我们看到firefox浏览器外观本⾝也是⽤跟扩展组件类似的结构搭建起来的,感兴趣的朋友可以解压 “C:\Program Files\Mozilla Firefox\chrome”⽬录下的jar⽂件观摩⼀下firefox浏览器外观的源代码,所以我们制作的扩展组件也会成为firefox浏览器⾃⾝的⼀部分,可以实
现⾮常强⼤⽽灵活的功能(例如Firebug这个神奇的组件)。相对来说,开发ie扩展程序显得困难多了,除⾮只是想做⼯具栏按钮和右键菜单(⽤注册表即搞定),否则需要使⽤VC,VB,Delphi这些⼯具开发COM组件才能完成。
如果想了解firefox浏览器本⾝各个元素的定义,但⼜不想阅读chrome⽬录下的脚本代码,可以安装 DOM Inspector 这个组件,这个组件有如开发web时的FireBug,是开发具有界⾯的扩展组件时的神兵利器!
提醒:⾃⼰编写的组件代码⽂件最好⽤“UTF-8”格式保存,⼀般可以减少很多⿇烦的问题。
2、认识install.rdf
install.rdf包含组件安装信息,本⽂例⼦中它的内容如下:
1. 1<?xml version="1.0" encoding="UTF-8"?>
2. 2<RDF xmlns="www.w
1999/02/22-rdf-syntax-ns#"
3. 3 xmlns:em="/2004/em-rdf#">
4. 4 <Description about="urn:mozilla:install-manifest">
5. 5 <em:id>uusharedemo1@uushare</em:id>
6. 6 <em:name>Uushare书签(⽰例)</em:name>
7. 7 <em:version>1.0</em:version>
8. 8 <em:creator>KwanhongYoung</em:creator>
9. 9 <em:description>这是⼀个模仿Uushare书签插件的⽰例</em:description>
10. 10 <em:homepageURL>www.uushare</em:homepageURL>
11. 11 <em:iconURL>chrome://uusharedemo1/content/uusharedemo1.png</em:iconURL>
12. 12 <em:targetApplication>
13. 13 <Description>
14. 14 <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- firefox -->
15. 15 <em:minVersion>1.5</em:minVersion>
16. 16 <em:maxVersion>3.0.*</em:maxVersion>
17. 17 </Description>
18. 18 </em:targetApplication>
19. 19 </Description>
20. 20</RDF>
21. 21
复制代码
⽂件⾥有很多是固定的写法,这⾥就不⼀⼀讲解了。
第5⾏的id是组件的⼀个标识符号,类似Windows⾥COM组件的CLSID,⽤于区别其他组件。可以使⽤这样类似email地址的格式组成,⽽这个“email地址”不要求是真实或有效的。也可以⽤的GUID来标识,例如“{c45c406e-ab73-11d8-be73-000a95be3b12}”是WebDevelop组件的标识符。
name、version、creator、description、homepageURL分别是组件的名称、版本、创建者的姓名、组件描述、组件官⽅⽹站地址。
iconURL⽤于显⽰组件的图标,格式⼀般⽤32x32pixel的png图⽚。
这⾥出现了chrome://这样的地址,跟和file://协议类似,chrome://也是⽤来定位资源的。格式是:
chrome://组件名称/⽬录路径/⽂件名
需要注意的是,这⾥的组件名称可以跟em:name属性中所指定的名称(⽤于显⽰的)不⼀样的,并且这个组件名称需要在chrome.manifest⾥定义。
这些信息在安装完组件之后能够在firefox的组件管理列表显⽰,如下图:
第14⾏⽐较重要,⽤于标识当前组件是⽤于哪个平台的(firefox/Thunderbird/SeaMonkey 等),如果开发的组件是给firefox⽤的,则id={ec8030f7-c20a-464f-9b0e-13a3a9e97384}。
第15、16⾏⽤于指定当前组件适⽤于firefox的哪些版本,因为firefox从1.5到3.0有些地⽅有所改变,所以如果你不知道⾃⼰的组件在哪些版本下可运⾏的话,最好先测试⼀下,然后准确地指定⼀个范围值,上例的值表⽰该组件适⽤于firefox1.5到3.0及3.0所有修订版。版本号码不能⾃⼰随便造,这⾥有⼀个完整的列表:
/en-US/firefox/pages/appversions
3、认识chrome.manifest
这是资源列表⽂件,内容如下:
1content uusharedemo1 chrome/content/
2locale uusharedemo1 en-US chrome/locale/en-US/
3skin uusharedemo1 classic/1.0 chrome/skin/
4overlay chrome://browser/content/browser.xul
chrome://uusharedemo1/content/firefoxOverlay.xul
5style chrome://global/content/customizeToolbar.xul
chrome://uusharedemo1/skin/overlay.css
前3⾏每⼀⾏表⽰⼀种类型的资源的地址,格式是:
资源名称<Tab>组件名称<Tab>参数<Tab>⽬录路径
其中组件名称是⾃定义的,只要跟其他组件名不⼀样并且使⽤全⼩写字母即可。定义好之后,就可以使⽤chrome://地址来定位资源了。例如,假设当前开发⽂件路径
是“c:/dev/uusharedemo1/”,那么:
chrome://uusharedemo1/content/uusharedemo1.png 实际指的是
c:/dev/uusharedemo1/chrome/content/uusharedemo1.png 这个⽂件。
第4⾏及第5⾏表⽰将当前组件的界⾯结合到系统本⾝的界⾯,因为当前组件会修改firefox本⾝的⼯具栏及右键菜单,所以需要加上这两⾏。
4、default/、skin/、locale/
这⼏个⽬录下的⽂件⽐较简单,下载本⽂的源代码查看⼀般能明⽩其中的意思,为了节约篇幅这⾥就不讲解了,等以后我写后续的章节时再详细介绍。
5、认识 content/firefoxOverlay.xul
Firefox的所有窗⼝都是使⽤xul⽂件定义的,例如在地址栏输⼊:
chrome://browser/content/aboutDialog.xul
(这个地址对应的源⽂件是:“C:\Program Files\Mozilla
Firefox\chrome\browser.jar/content/aboutDialog.xul”
就可以看到firefox的“关于”对话框,在这个例⼦⾥我们⽤firefoxOverlay.xul定义⼀个⼯具栏按钮、右键菜单以及⼀个⼯具菜单项,源代码如下:
1. 1<?xml version="1.0" encoding="UTF-8"?>
2. 2<!-- 下⾯⼀⾏指明当前窗⼝控件所引⽤的样式表⽂件 -->
chrome浏览器官方3. 3<?xml-stylesheet href="chrome://uusharedemo1/skin/overlay.css" type="text/css"?>
4. 4
5. 5<!-- 这⾏指明当前窗⼝控件所使⽤的语⾔⽂件,注意这⾥不需指定语⾔的名称(即zh-CN
或en-US等),只需指明⽂件名即可
6. 6有了语⾔⽂件之后,所有控件的⽂本(即text/label等属性)都统⼀写到语⾔⽂件⾥。 -->
7. 7<!DOCTYPE overlay SYSTEM "chrome://uusharedemo1/locale/uusharedemo1.dtd">
8. 8
9. 9<overlay id="uusharedemo1-overlay"
10. 10 xmlns="/keymaster/gatekeeper/ly.xul">
11. 11
12. 12 <!-- 这⾏⽤于指定当前窗⼝控件的事件(如单击事件)触发后所执⾏的代码所在的⽂件
-
->
13. 13 <script src="overlay.js"/>
14. 14 <stringbundleset id="stringbundleset">
15. 15 <stringbundle id="uusharedemo1-strings"
src="chrome://uusharedemo1/locale/uusharedemo1.properties"/>
16. 16 </stringbundleset>
17. 17
18. 18 <menupopup id="menu_ToolsPopup">
19. 19 <menuitem id="uusharedemo1-hello" label="&uusharedemo1.label;"
20. 20 oncommand="MenuItemCommand(event);"/>
21. 21 </menupopup>
22. 22
23. 23 <popup id="contentAreaContextMenu">
24. 24 <menuitem id="context-uusharedemo1" label="&uusharedemo1Context.label;"
25. 25 accesskey="&uusharedemo1Context.accesskey;"
26. 26 insertafter="context-stop"
27. 27 oncommand="MenuItemCommand(event)"/>
28. 28 </popup>
29. 29
30. 30 <toolbarpalette id="BrowserToolbarPalette">
31. 31 <toolbarbutton id="uusharedemo1-toolbar-button"
32. 32 label="&uusharedemo1Toolbar.label;"
33. 33 tooltiptext="<ip;"
34. 34 oncommand="ToolbarButtonCommand()"
35. 35 class="toolbarbutton-1 chromeclass-toolbar-additional"/>
36. 36 </toolbarpalette>
37. 37</overlay>
复制代码
menupopup 段定义了⼀个位于“⼯具”菜单栏下的项⽬,其中id是菜单项的名称,我们⾃⼰添加的菜单项、按钮等结合到firefox本⾝的控件的id必须惟⼀;label属性是菜单项显⽰的⽂本,这⾥因为引⽤了语⾔⽂件,所以真正显⽰的⽂本内容位于语⾔⽂件(uusharedemo1.dtd)⾥标有uusharedemo1.label 这⾏定义的后⾯;oncommand属性定义菜单被点击后执⾏ overlay.js ⾥⾯的那⼀个⽅法过程。
popup 段定义了⼀个右键菜单项,accesskey为菜单项的快捷键(即带下划线的字
母),insertafter为新菜单项所出现的位置位于id为 “context-stop”(即“停⽌”)这项的后⾯,如何得知某
⼀项菜单项的id呢?出动Dom Inspector 吧。包括firefox⼯具栏上⾯的所有按钮的id,都可以⽤Dom Inspector查看得知。
toolbarpalette段定义了⼀个⼯具栏按钮,其中tooltiptext为⿏标停留在这个新按钮上⾯时所显⽰的提⽰⽂本。
上⾯⼀段代码并没有定义⾃⼰的窗⼝,我会在下⼀章再讲解。
6、认识content/overlay.js
overlay.js ⽂件是专门为上⾯的firefoxOverlay.xul服务的,(怎么知道的呢?在firefoxOverlay.xul ⽂件的第13⾏有引⽤啊)。在 xul⽂件⾥可以看到菜单被点击之后会调⽤⼀个名
叫“onMenuItemCommand”的⽅法过程,⽽⼯具栏按钮被点击之后会调⽤“onToolbarButtonCommand”⽅法过程。我们想在他们被点击之后做什么事情呢?为了演⽰如何在js⾥编写调⽤firefox对象的代码,这⾥模仿uushare书签的功能,让菜单和按钮点击之后调⽤Uushare⽹站上的书签服务的添加书签的接⼝,接⼝是这样的:
www.uushare/bookmark/save?
v=1&client=ff10&noui=yes&jump=close&url=XXXX&title=YYYY&content=ZZZZ
其中XXXX为待收藏的⽹页地址,YYYY是⽹页的标题,ZZZZ是⽹页中选中的⽂本。所以我们需要在js⾥获取当前⽹页的URL、Title以及被选中的⽂本。
下⾯是例⼦中的代码:
1. 1var uusharedemo1 = {
2. 2 onLoad: function() {
3. 3 // initialization code
4. 4 this.initialized = true;
5. 5 this.strings = ElementById("uusharedemo1-strings");
6. 6 ElementById("contentAreaContextMenu")
7. 7 .addEventListener("popupshowing", function(e) { this.showContextMenu(e); },
false);
8. 8 },
9. 9
10. 10 showContextMenu: function(event) {
11. 11 // 根据上下⽂决定显⽰/隐藏右键菜单项
12. 12 // see [url]/Adding_items_to_menus[/url]
13. 13 ElementById("context-uusharedemo1").hidden =
14. 14 },
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论