zoukankan      html  css  js  c++  java
  • 使用 XUL 实现浏览器扩展,第 2 部分: 组建一个跨平台的 Firefox 扩展

    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 文件目录
                    
    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>


    我将在稍后一节中进一步讨论 chrome URL。请注意文档类型声明,它用于加载一个 DTD,其中包含所有应进行本地化的字符串(基本上包括呈现给用户的所有自然语言字符串)。下一节将更详细介绍这种在 Mozilla chrome 应用程序中实现本地化(l10n)的好方法。在覆盖 XUL 内部,我指定了一个新增的菜单项。outer 元素根据 ID 指定 Firefox 中的现有目标菜单项 — 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 为用户重新调整窗口大小提供控件。





    回页首


    chrome 资源

    您现在已经了解到,围绕该扩展新增了很多文件,并且 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/


    第一行确定主要内容的位置,例如 XUL 文件和脚本。它使用 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(.),我获得了字符计数(计算字符串长度)和单词数(使用空格将字符串断开并计算结果)。通过第二个表达式 //*,我获得了元素的总数。随后我将使用这些值更新相应的文本框。

  • 相关阅读:
    杭电 Problem
    杭电Problem 5053 the sum of cube 【数学公式】
    杭电 Problem 2089 不要62 【打表】
    杭电 Problem 4548 美素数【打表】
    杭电 Problem 2008 分拆素数和 【打表】
    杭电 Problem 1722 Cake 【gcd】
    杭电 Problem 2187 悼念512汶川大地震遇难同胞——老人是真饿了【贪心】
    杭电Problem 1872 稳定排序
    杭电 Problem 1753 大明A+B
    东北林业大 564 汉诺塔
  • 原文地址:https://www.cnblogs.com/ice5/p/1377005.html
Copyright © 2011-2022 走看看