Firefox插件开发
写在开头
因为某些原因,想删除所有Qzone的心情,从同事那边得出并没有提供该批量删除的功能接口,于是想到使用firefox写一个插件,于是就有了一个称之为forgot1.0的小东西,把从零开始学习firefox插件开发(其实也不算,JS和css我还是会的,虽然因为做后台开发已经很久没有碰过了)的过程记录下来,也重拾写blog的习惯。
1 插件结构
Firefox的插件,其实就是一个以xpi为后缀名的zip压缩文件,当我们利用winrar解压xpi文件后,目录结构如下:
/install.rdf
/components/*
/components/cmdline.js
/defaults/
/defaults/preferences/*.js
/plugins/*
/chrome.manifest
/chrome/icons/default/*
/chrome/
/chrome/content/
1.1 install.rdf
从名字可以看出,这个文件描述了扩展安装所需要的信息,包括了扩展的标识、版本、适用的应用程序、作者等等。
基本的install.rdf示例:
<?xmlversion="1.0"?>
<RDFxmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<!-- 标识和版本 -->
<Descriptionabout="urn:mozilla:install-manifest">
<em:id>coreymylife@163.com</em:id>
<em:version>1.0</em:version>
<em:type>2</em:type>
<!-- 针对的应用程序 -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>1.5</em:minVersion>
<em:maxVersion>*</em:maxVersion>
</Description>
</em:targetApplication>
<!-- 名称、介绍、作者和网站地址 -->
<em:name>forgot</em:name>
<em:description>空间签名删除器</em:description>
<em:creator>corey</em:creator>
<em:homepageURL>http://blog.csdn.net/turkeyzhou</em:homepageURL>
</Description>
</RDF>
em:id段是此软件包唯一的标识,可以是作者的email,目的是唯一标识此软件包。
em:type值为2代表"我是扩展",4代表"我是主题",这里是扩展,所以值为2
em:targetApplication段描述了软件包针对的应用程序,其中em:id表明此扩展是针对firefox的,而不是thunderbird、sunbird,所以,只要是针对firefox的扩展,此id的值都不变。
minVersion,maxVersion分别表示插件支持的最小和最大的firefox版本,如果无上限,则一般将maxVersion设置为*。
最后的em:name,em:description,em:creator,em:homepageURL描述了扩展的基本信息,从标签的名称上就可以看出意思,扩展管理器中显示的扩展信息,就是来源于这里。
1.2 chrome
chrome一般包括3类文件,content、locale、skin:
content:描述扩展界面、外观的定义文件,比如按钮布局,对话框,通过XUL文件和js文件来设定,后面我们可以看到XUL的介绍。
locale: 描述多语言信息的文件,一般是xml的dtd文件。
skin: 定义界面样式的css文件和所需要的图片文件。
1.3 chrome.manifest文件
首先,我们必须明白chrome://是什么,chrome://其实相当于http一样,是firefox定位扩展文件的一种链接方式。
如果我们在firefox地址栏中输入chrome://browser/content/browser.xul,你则会发现窗口中有嵌套了一个窗口,而这个窗口本身可以认为是一个xul,所以,chrome://可以认为是一种定位资源文件的方式(如同http:// file://等scheme等)。
在文件开头,你首先得定义一个chrome资源,如:
content forgot chrome/content/
分别为:
context domain path
则chrome完整的引用路径为:
chrome://domain/context/filename
另外我们必须了解一下overlay,从字面上来说,overlay是覆盖的意思,下面这一行:
overlay chrome://browser/content/browser.xul chrome://forgot/content/forgot.xul
表示浏览器在加载的时候,将自动加载forgot.xul。
2 XUL
在Firefox中,所有的界面都是基于XUL文件描述的,XUL本身是一个XML文件。就连Firefox本身,也是基于XUL的。
如:
<?xml version="1.0"?>
<?xml-stylesheethref="chrome://global/skin/" type="text/css"?>
<window>
id="test-window"
title="窗口"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
</window>
我们可以在firefox中直接打开这个文件,并能看到该文件所代表的窗口。XUL中的空间和HTML的控件几乎是一一对应的,可以参考更多的XUL的资料了解,如下是一个iframe的空间的使用。
<?xml version="1.0"?>
<?xml-stylesheethref="chrome://global/skin/" type="text/css"?>
<window>
id="test-window"
title="窗口"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<iframe id="content"src="http://blog.csdn.net/tyurkeyzhou" flex="1"/>
</window>
可以通过XUL在浏览器的status bar中添加一个按钮:
<?xmlversion="1.0"?>
<overlayid="forgot"xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/x-javascript"src="chrome://forgot/content/jquery-1.7.2.min.js"/>
<scripttype="application/x-javascript"src="chrome://forgot/content/forgot.js"/>
<statusbarid="status-bar">
<statusbarpanelid="forgot" label="forgot" οnclick="Man.forgot()" />
</statusbar>
</overlay>
也可以通过XML在浏览器的菜单栏中新增一个菜单项:
<?xmlversion="1.0"?>
<!DOCTYPE overlay SYSTEM"chrome://meetmeplus/locale/overlay.dtd">
<?xml-stylesheet href="chrome://meetmeplus/skin/default.css"type="text/css"?>
<overlay id="mmp-overlay"xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<!-- Firefox toolbar -->
<toolbarpalette id="BrowserToolbarPalette">
<toolbarbuttonid="meetmeplus-button" type="menu-button"
class="toolbarbutton-1 chromeclass-toolbar-additional">
<menupopup>
<menuitem label="&mmp.gotohome;"tooltiptext="&mmp.gotohome.tooltip;" image="chrome://meetmeplus/skin/option_16.png"class="menuitem-iconic"/>
<menuseparator/>
<menuitem label="&mmp.option;"tooltiptext="&mmp.option.tooltip;"image="chrome://meetmeplus/skin/option_16.png" class="menuitem-iconic"/>
</menupopup>
</toolbarbutton>
</toolbarpalette>
</overlay>
弹出菜单XUL如下:
<?xml version="1.0"?>
<overlay id="sample"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/x-javascript" src="overlay.js"/>
<menupopup id="menu_ToolsPopup">
<menuitem id="getcurrenturl" label="CurrentURL" oncommand="getURL();"/>
</menupopup>
</overlay>
3 事件点击响应与JS
下面是XUL定义的一个按钮:
<buttonlabel="普通的按钮"oncommand="alert('onclick')"/>
或者在XUL开头引入JS文件
<script type="application/x-javascript"src="chrome://forgot/content/jquery-1.7.2.min.js"/>
<scripttype="application/x-javascript"src="chrome://forgot/content/forgot.js"/>
<statusbarid="status-bar">
<statusbarpanelid="forgot" label="forgot"οnclick="Man.forgot()" />
</statusbar>
其中event参数可以获取事件源的相关信息,clientX、clientY、screenX、screenY,分别是事件触发时,鼠标相对文档的xy坐标值和相对整个屏幕的xy坐标值,第21行在hbox上设置了onmousemove的事件属性,每当鼠标在这个hbox上移动,就会触发函数显示当前鼠标的位置。如event.target.tagName 获得被激活的控件的标签名称:
oncommand="alert(event.target.tagName );
也可以在代码中绑定:
/*
* 参数1为事件名称,oncommand即为command
* 参数2为事件处理函数
* 参数3为true 表示不捕捉冒泡消息
*/
button.addEventListener('command',show_ok, true);
4 快捷键
为XUL元素设置快捷键的方法有多种。
l 元素accessKey属性,如:
<menuitemid="close-command" label="关闭(X)"accesskey="x"/>
l 全局快捷键Key元素,设置的快捷键是crtl+q,modifiers就是通常所说的修饰键,modifiers可以取control、alt、meta、shift,分别代表了键盘上的ctrl、alt、meta、shift键。设置的快捷键是ctrl+alt+c,演示了如何设置有两个修饰键的情况,只需把他们用空格分开即可。如:
<keyset>
<keyid="key1" modifiers="control" key="Q"oncommand="alert('你按了快捷键crtl+Q')"/>
<keyid="key2" modifiers="control alt" key="C"oncommand="alert('你按了快捷键crtl+alt+C')"/>
<keyid="key3" keycode="VK_F6" oncommand="alert('你按了快捷键F6')"/>
</keyset>
5 事件驱动
我们可以利用元素的addEventListener方法绑定事件
element.addEventListener(eventType,function,boolean)
而全局函数会将函数绑定到全局的元素上
addEventListener(eventType,function,boolean)
另外,元素的时间处理逻辑可以通过command元素与页面元素分离,如:
<command id="cmd_1" oncommand="alert('hello ');"/>
元素通过如下方式进行绑定:
<button label="还是帮助" command=" cmd_1"/>
6 发布
将xpi上传至install.rdf文件所注明的服务器位置,并且修改响应的容易的处理content-type,在httpd.conf或者.htaccess文件中添加:
AddTypeapplication/x-xpinstall .xpi
如果需要自动更新,则需要如下四部:
n 生成新的xpi文件。
n Sha1sum xpi文件,将得到的hash写入update.rdf
n McCoy Sign update.rtf
n 上传update.rdf和xpi文件至服务器
7 结尾语
没有什么好说的,用到了就总结一下,如果需要开发复杂的插件,这些只是远远不够的,但对于程序员而言,一切都是从hello world开始。
参考文献:
https://addons.mozilla.org/en-US/developers/docs/reference
https://developer.mozilla.org/en/Extensions
http://www.ibm.com/developerworks/cn/web/wa-lo-firefox-ext/#chrome-sidebar