使用 XUL 实现浏览器扩展,第 2 部分: 组建一个跨平台的 Firefox 扩展
2009-01-16 14:08
741 查看
Mozilla 的 XUL 用户界面语言(XML User Interface Language,XUL)是一种可用于开发独立应用程序和浏览器扩展的通用语言。在 本系列第 1 部分 中,我展示了 XUL 扩展的基本构建块,本文则介绍如何将这些构建块组装为一个跨平台的 Firefox 扩展。由于对浏览器中的 XUL 文件存在较高的安全要求,第 1 部分中的代码功能非常有限,但是扩展则没有这么多限制,因此我还将在本文中提供一些代码中缺失的功能。
基本的扩展结构
第 一步是使用前一篇文章中生成的 XUL 和支持文件构建扩展。如果您已安装了其他 Firefox 加载项,您可能注意到它们随附在文件扩展名为 .xpi 的包里,它表示 XUL 的跨平台安装包(XPI)格式(读作 “zippy”)。XPI 定义了一些包,这些包均为 .zip 文件,并且都具有特定的布局和一些清单(manifest)文件。这类似于 Java 的 JAR 格式,后者也在 .zip 内容中包含了清单文件。清单 1 显示了 .zip 文件目录,用于放置我在上一篇文章中使用 XUL、JavaScript 和 CSS 生成的扩展。
清单 1. 用于 Firefox 扩展 XPI 包的 .zip 文件目录
请仔细检查文件布局,因为开发扩展过程中最大的难题可能就源于这里。您可能会注意到,有几个新文件并没有出现在上一篇文章里,我将在下一小节介绍这些文件。
XUL 覆盖
在上一篇文章中,新的 XUL 窗口是完全独立的,但是现在它被绑定为一个扩展,必须以某种方式从 Firefox 中调用。这通常要对浏览器用户界面进行调整,以为用户提供调用扩展的方法。XUL 通过提供称为覆盖(overlay)的方式可以轻松地对用户界面进行扩展。清单 2(overlay.xul)显示了一个覆盖,它添加了一个菜单项来启动 stats 查看器窗口。
清单 2 (overlay.xul). XUL 覆盖添加了一个菜单项
我将在稍后一节中进一步讨论 chrome URL。请注意文档类型声明,它用于加载一个 DTD,其中包含所有应进行本地化的字符串(基本上包括呈现给用户的所有自然语言字符串)。下一节将更详细介绍这种在 Mozilla chrome 应用程序中实现本地化(l10n)的好方法。在覆盖 XUL 内部,我指定了一个新增的菜单项。outer 元素根据 ID 指定 Firefox 中的现有目标菜单项 —
清单 3 (overlay.js). 脚本为所添加的菜单项提供操作
脚本的主要内容是定义了一个单独的结构
chrome 资源
您现在已经了解到,围绕该扩展新增了很多文件,并且 XPI 的一个重要方面就是在包内查找文件。这时就需要使用到清单文件 chrome.manifest,如清单 4 所示。
清单 4. 针对 Stats 扩展的 chrome 清单文件
第一行确定主要内容的位置,例如 XUL 文件和脚本。它使用
安装程序设置
XPI 的另一个关键信息文件是 install.rdf,如清单 5 所示,其中包含了扩展安装说明。
清单 5 (install.rdf). Stats 扩展的安装参数
大部分内容的含义不言自明,因此就不多做说明,但是需要提到的一点是,我使用
您应该能够将上一篇文章中的示例文件放入清单 1 中指出的位置,惟一所做的修改是将 “stats.xul” 中的 CSS 链接(用于假定 “stats.css” 位于同一个目录中)改为使用 chrome 链接
完善扩展的功能
由于安全限制,我不得不去掉了 stats.js XUL 文件中的一些功能。现在我已经将它打包为一个扩展,可以补充一些缺失的内容。清单 6 展示了更新后的 stats.js,它实际执行了扩展所期望的计数操作。
清单 6. Stats 查看器窗口的完整 JavaScript 代码
这一次,我对用户加载到
基本的扩展结构
第 一步是使用前一篇文章中生成的 XUL 和支持文件构建扩展。如果您已安装了其他 Firefox 加载项,您可能注意到它们随附在文件扩展名为 .xpi 的包里,它表示 XUL 的跨平台安装包(XPI)格式(读作 “zippy”)。XPI 定义了一些包,这些包均为 .zip 文件,并且都具有特定的布局和一些清单(manifest)文件。这类似于 Java 的 JAR 格式,后者也在 .zip 内容中包含了清单文件。清单 1 显示了 .zip 文件目录,用于放置我在上一篇文章中使用 XUL、JavaScript 和 CSS 生成的扩展。
清单 1. 用于 Firefox 扩展 XPI 包的 .zip 文件目录
Archive: /Users/uche/stats.xpi Length Method Size Ratio Date Time CRC-32 Name -------- ------ ------- ----- ---- ---- ------ ---- 0 Stored 0 0% 10-08-07 23:10 00000000 chrome/ 0 Stored 0 0% 10-08-07 23:10 00000000 chrome/content/ 271 Defl:N 184 32% 10-09-07 00:13 44bb6d65 chrome/content/overlay.js 464 Defl:N 284 39% 10-09-07 00:13 1d873c24 chrome/content/overlay.xul 909 Defl:N 366 60% 10-09-07 00:13 67869f05 chrome/content/stats.js 1581 Defl:N 544 66% 10-09-07 00:13 49def584 chrome/content/stats.xul 0 Stored 0 0% 10-08-07 23:10 00000000 chrome/skin/ 230 Defl:N 147 36% 10-09-07 00:13 a732aecb chrome/skin/stats.css 181 Defl:N 105 42% 10-09-07 00:13 f7317c0a chrome.manifest 0 Stored 0 0% 10-08-07 23:10 00000000 defaults/ 0 Stored 0 0% 10-08-07 23:10 00000000 defaults/preferences/ 948 Defl:N 440 54% 10-09-07 00:13 50ee7971 install.rdf 0 Stored 0 0% 10-08-07 23:10 00000000 locale/ 0 Stored 0 0% 10-08-07 23:10 00000000 locale/en-US/ 43 Stored 43 0% 10-09-07 00:13 d9c38400 locale/en-US/overlay.dtd -------- ------- --- ------- 4627 2113 54% 15 files |
XUL 覆盖
在上一篇文章中,新的 XUL 窗口是完全独立的,但是现在它被绑定为一个扩展,必须以某种方式从 Firefox 中调用。这通常要对浏览器用户界面进行调整,以为用户提供调用扩展的方法。XUL 通过提供称为覆盖(overlay)的方式可以轻松地对用户界面进行扩展。清单 2(overlay.xul)显示了一个覆盖,它添加了一个菜单项来启动 stats 查看器窗口。
清单 2 (overlay.xul). XUL 覆盖添加了一个菜单项
<?xml version="1.0"?> <?xml-stylesheet href="chrome://stats/skin/overlay.css" type="text/css"?> <!DOCTYPE overlay SYSTEM "chrome://stats/locale/overlay.dtd"> <overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="stats-overlay"> <script src="overlay.js"/> <menupopup id="menu_ToolsPopup"> <menuitem id="stats" label="&statsmenuitemname;" oncommand="Stats.onMenuItemCommand(event);"/> </menupopup> </overlay> |
menu_ToolsPopup是 “Tools” 菜单。新的菜单项在默认情况下作为最后一个菜单项添加。新的菜单项
stats以 DTD 实体的形式提供,对用户看到的标签使用一个经过本地化的字符串。
oncommand属性非常关键,因为它可以确定当用户选择菜单项时发生什么操作。指定的 JavaScript 函数通过独立的脚本文件 overlay.js 提供,如清单 3 所示。
清单 3 (overlay.js). 脚本为所添加的菜单项提供操作
var Stats = { onLoad: function() { //You can place set-up code for the extension here }, onMenuItemCommand: function() { window.open("chrome://stats/content/stats.xul", "", "chrome, resizable=yes"); } }; window.addEventListener("load", function(e) { Stats.onLoad(e); }, false); |
Stats, 使用它封装所有函数。您还需要将所有全局变量放入该结构中。这将减少扩展的内存占用,因为它在全局名称空间(outer 结构本身的名称)中只会占用一个名称,并且对于所有表现良好的扩展来说,这是一项标准行为,可以避免与其他扩展甚至是内容脚本发生对象名冲突。您已经了解 了如何使用 JavaScript 代码片段
Stats.onMenuItemCommand(event);访问清单 2 中的封装对象,这段代码将访问清单 3 中的第二个结构项。为保持完整性,我包括了一个
Stats.onLoad函数,但是扩展并没有实际使用到它。您将使用它运行任何扩展初始化代码。脚本的最后一行对
Stats.onLoad函数进行了设置,以便在 chrome 完成加载后立即运行该函数。
Stats.onMenuItemCommand函数使用上一篇文章中的 XUL 示例 applet 启动窗口。它的第二个属性是我没有使用到的窗口 ID。第三个属性为标志列表
chrome,表示新窗口具有自己的 chrome,并且不应该在浏览器的 chrome 内打开(因此,新窗口不能继承 Firefox 的菜单、工具栏、状态条、选项卡等等)。
resizable=yes为用户重新调整窗口大小提供控件。
|
您现在已经了解到,围绕该扩展新增了很多文件,并且 XPI 的一个重要方面就是在包内查找文件。这时就需要使用到清单文件 chrome.manifest,如清单 4 所示。
清单 4. 针对 Stats 扩展的 chrome 清单文件
content stats chrome/content/ overlay chrome://browser/content/browser.xul chrome://stats/content/overlay.xul locale stats en-US locale/en-US/ skin stats classic/1.0 chrome/skin/ |
stats别名指代包的 “chrome/content/” 文件夹,因此,举例来说,如果使用的 chrome URL 为
chrome://stats/content/stats.xul,则将通过映射
stats别名对 URL 进行解析并在 “chrome/content/” 文件夹查找 “stats.xul” 文件。第二行使用 overlay.xul(清单 2)对主浏览器 chrome 建立一个覆盖。第三行确定包含自然语言字符串的 DTD 的位置,为本地化(l10n)提供支持。示例中仅包含这些字符串的英文版本,但是您可以将这些字符串翻译为法文然后放到
fr-FR文件夹中,或者翻译为德文放到
de-DE文件夹中,等等。浏览器将自动使用和用户设置的首选语言相对应的语言。最后一行为 CSS 文件建立了一个位置,这些文件将与标准浏览器 chrome 结合在一起。
安装程序设置
XPI 的另一个关键信息文件是 install.rdf,如清单 5 所示,其中包含了扩展安装说明。
清单 5 (install.rdf). Stats 扩展的安装参数
<?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"> <!-- Required Items --> <em:id>xulapp@example.com</em:id> <em:name>Stats viewer</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>2.0.0.*</em:maxVersion> </Description> </em:targetApplication> <!-- Optional Items --> <em:creator>Uche Ogbuji</em:creator> <em:description> Opens a window in which you can view simple stats about Web pages </em:description> <em:homepageURL>http://www.ibm.com/developerworks/web/</em:homepageURL> </Description> </RDF> |
em:targetApplication元素指定所有的 Firefox 版本大于 1.5 而小于 2.0.1。较长的
em:id字符串是 Firefox 自身的应用程序全球惟一标识符(UUID)。
您应该能够将上一篇文章中的示例文件放入清单 1 中指出的位置,惟一所做的修改是将 “stats.xul” 中的 CSS 链接(用于假定 “stats.css” 位于同一个目录中)改为使用 chrome 链接
chrome://stats/skin/stats.css。
完善扩展的功能
由于安全限制,我不得不去掉了 stats.js XUL 文件中的一些功能。现在我已经将它打包为一个扩展,可以补充一些缺失的内容。清单 6 展示了更新后的 stats.js,它实际执行了扩展所期望的计数操作。
清单 6. Stats 查看器窗口的完整 JavaScript 代码
//Invoked in response to a click on the "Go!" button function change_url(event) { //Variables for convenient access to specific elements in the XUL var urlbox = document.getElementById("url"); var contentview = document.getElementById("contentview"); var wordcountbox = document.getElementById("wordcount"); var charcountbox = document.getElementById("charcount"); var elemcountbox = document.getElementById("elemcount"); alert(urlbox.value); contentview.contentDocument.location.href = urlbox.value; //Use Firefox XPath to get the raw text of the document var doctext = contentview.contentDocument.evaluate( "string(.)", document, null, XPathResult.STRING_TYPE, null).stringValue; var wordcount = doctext.split(" ").length() alert(wordcount); wordcountbox.value = String(wordcount); charcountbox.value = String(doctext.length()); //Use Firefox XPath to count elements in the document var elemcount = contentview.contentDocument.evaluate( "count(//*)", document, null, XPathResult.NUMBER_TYPE, null).numberValue; elemcountbox.value = String(elemcount); } |
contentview的 Web 页面使用了两个 XPath 表达式。通过第一个表达式
string(.),我获得了字符计数(计算字符串长度)和单词数(使用空格将字符串断开并计算结果)。通过第二个表达式
//*,我获得了元素的总数。随后我将使用这些值更新相应的文本框。
相关文章推荐
- 使用 XUL 实现浏览器扩展,第 2 部分: 组建一个跨平台的 Firefox 扩展
- 使用 XUL 实现浏览器扩展,第 1 部分: 使用用户界面特性创建一个 Firefox 浏览
- 使用 XUL 实现浏览器扩展,第 1 部分:使用用户界面特性创建一个 Firefox 浏览器扩展
- 使用 XUL 实现浏览器扩展,第 1 部分: 使用用户界面特性创建一个 Firefox 浏览器扩展
- Rational Functional Tester Proxy SDK 开发,第 2 部分: 使用 Proxy SDK 扩展 RFT 已支持 Java GUI 组件 Proxy 对象实现
- 使用 JSONP 实现跨域通信,第 2 部分: 使用 JSONP、jQuery 和 Yahoo! 查询语言构建 mashup
- 使用 IIS 进行 Microsoft ASP.NET 2.0 成员/角色管理,第 2 部分:实现
- Redis的安装、使用以及php中扩展redis并实现php操作redis的一个例子
- 使用开放源代码框架的 Java 应用程序的 Web 服务集成模式,第 2 部分: 实现接收模式
- [原创]实现与服务器时间同步的跨平台JS脚本 支持IE , firefox , Opera ,Netscape 等主流浏览器
- 创建您自己的浏览器扩展,第二部分: 将您的触角延伸至 Firefox
- firefox + pentadactyl 实现纯绿色高效易扩展浏览器(同时实现修改默认状态栏样式)
- 一个图片轮换显示的实现,使用DIV+JS,支持Firefox,IE,Safiri
- 201512011linux系统日常管理第三部分(使用tshark抓包分析http请求,iptables 针对一个网段)扩展1
- 使用Firefox浏览器创建一个jQuery沙箱
- 编写一个聊天程序:有接收数据部分,和发数据的部分, 这两部分需要同时执行,使用多线程实现,一个控制接收,一个控制发送
- [转]使用 PHP 实现云计算,第 2 部分: 通过 Zend Framework 使用 Amazon EC2
- 使用 Apache Solr 实现更加灵巧的搜索,第 2 部分: 用于企业的 Solr
- 使用wxpython实现的一个简单图片浏览器实例
- Python 中的线性优化,第 2 部分: 在云中构建一个可扩展的基础架构