如何从头开始打包 Firefox 扩展

How to pack a Firefox extension from scratch

我是 Firefox 扩展的新手,我希望你能帮我打包一个我构建的扩展并将其发送给一些朋友进行测试。

我的扩展即将 "block" 一些 URL。这意味着如果有人试图加入 "facebook.com" 我的分机应该将他重定向到 "www.google.com"

代码如下。

const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import('resource://gre/modules/Services.jsm');
var urls_block = [ 
    //If URLs contain any of these elements they will be blocked or redirected,
    //  your choice based on code in observer line 17
    'www.facebook.com',
     'www.apple.com'
];
var redir_obj = {
    'www.facebook.com': 'http://www.google.com/',
    'www.apple.com': 'http://www.samsung.com'
}
var observers = {
    'http-on-modify-request': {
        observe: function (aSubject, aTopic, aData) {
            console.info('http-on-modify-request: aSubject = ' 
                          + aSubject + ' | aTopic = ' + aTopic + ' | aData = ' + aData);
            var httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
            var requestUrl = httpChannel.URI.spec.toLowerCase();
            for (var i=0; i<urls_block.length; i++) {
                if (requestUrl.indexOf(urls_block[i]) > -1) {
                    //httpChannel.cancel(Cr.NS_BINDING_ABORTED); //this aborts the load
                    //Can redirect with this next line, if don't want to redirect and
                    //  just block, then comment this line and uncomment the line above:
                    httpChannel.redirectTo(Services.io.newURI(redir_obj[urls_block[i]],
                                               null, null));
                    break;
                }
            }
        },
        reg: function () {
            Services.obs.addObserver(observers['http-on-modify-request'],
                                           'http-on-modify-request', false);
        },
        unreg: function () {
            Services.obs.removeObserver(observers['http-on-modify-request'], 
                                           'http-on-modify-request');
        }
    }
};
function install() {}
function uninstall() {}
function startup() {
    for (var o in observers) {
        observers[o].reg();
    }
}

function shutdown(aData, aReason) {
    if (aReason == APP_SHUTDOWN) return;

    for (var o in observers) {
        observers[o].unreg();
    }
}

非常感谢@Noitidart 的巨大帮助。

所以我想为 Firefox Extension 打包这段代码。 有人可以告诉我怎么做或任何例子吗?

非常感谢您花时间在这里帮助我。

您至少需要创建一个 install.rdf file and a chrome.manifest 文件。通过这些链接,您将需要做出一些选择(例如,如何调用您的分机、<em:id> 等)。

此外,您似乎正在制作 bootstrap/restartless add-on and should call the file containing the code you included in the question: bootstrap.js

.xpi file format (Extension Packaging):

用作 Mozilla(Firefox、Thunderbird 等)扩展容器的 .xpi 文件仅仅是文件扩展名更改为 .xpi 的 zip 压缩存档。这些文件从 zip 压缩存档的根目录开始(即第一级目录包含这些文件)。文件必须未压缩或使用 "Deflate" 算法压缩。使用其他压缩算法将导致您的 .xpi 文件无法加载,并且会弹出一个插件已损坏的窗口。

存档的内容可以是几个文件到任意数量的文件。至少,您有一个 install.rdf and a chrome.manifest 文件。几乎总会有至少一个附加文件(如果附加文件不多的话)。

我的非常简单Bootstrap/Restartless extension, Print Button is Print(将打印按钮更改为打印而不是打印预览),具有以下结构:

Archive contains:
  bootstrap.js
  chrome/
  chrome/content/
  chrome/content/options.xul
  chrome/skin/
  chrome/skin/printer-typeC128.png
  chrome/skin/printer-typeC32.png
  chrome/skin/printer-typeC48.png
  chrome/skin/printer-typeC64.png
  chrome.manifest
  install.rdf
  license.txt
Total 12 entries (42360 bytes)
  • 有所需的 install.rdf and chrome.manifest 个文件。
  • 文件 bootstrap.js is required for Bootstrap/Restartless 扩展名。它包含扩展安装、删除、启用、禁用或 Firefox 启动或关闭时 运行 的代码。这个扩展非常简单,所有 JavaScript 代码都包含在 bootstrap.js 中。
  • 有一个文件 chrome/content/options.xul,它是 options dialog 的 XUL 定义。
  • license.txt只是说明扩展是在Mozilla Public License, v2.0下发布的。
  • .png 个文件是此扩展在各种分辨率下的图标。

Print Button 的 install.rdf 文件是 Print is(PrintButtonIsPrint 的所有实例都应更改为您在chrome.manifest 文件;如果你想删除所有这些,你可以从 instal.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">
    <em:id>PrintButtonIsPrint@makyen.foo</em:id> <!-- MUST be unique to your extension. -->
    <em:version>1.0.1</em:version>
    <em:type>2</em:type>
    <em:name>Print Button is Print</em:name> <!-- Should be unique to your extension. -->
    <em:bootstrap>true</em:bootstrap> <!-- Indicate that the extension is restartless -->
    <em:unpack>false</em:unpack>
    <em:description>Makes the Print Button print the page instead of presenting a print preview. Adds the option of using shift-left-click and/or ctrl-left-click for Print Preview (both enabled by default).</em:description>
    <em:creator>Makyen</em:creator>
    <!-- No about.
    <em:aboutURL>chrome://PrintButtonIsPrint/content/about.xul</em:aboutURL>
    -->
    <em:optionsURL>chrome://PrintButtonIsPrint/content/options.xul</em:optionsURL>
    <em:iconURL>chrome://PrintButtonIsPrint/skin/printer-typeC48.png</em:iconURL> 
    <em:icon64URL>chrome://PrintButtonIsPrint/skin/printer-typeC64.png</em:icon64URL> 
<!--Firefox-->
    <em:targetApplication>
        <Description>
            <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
            <em:minVersion>29.0</em:minVersion>
            <em:maxVersion>37.*</em:maxVersion>
        </Description>
    </em:targetApplication>
    </Description>
</RDF>

chrome.manifest 是(PrintButtonIsPrint 的两个实例都应更改为适合您的扩展的内容):

content      PrintButtonIsPrint                                         chrome/content/
skin         PrintButtonIsPrint               classic/1.0               chrome/skin/

为了创建 .xpi 文件,我使用了一个批处理文件,它结合了 DOS 和 Unix/Linux(实际上是 Cygwin)命令:

mkxpi.bat:

rm -f PrintButtonIsPrint@makyen.foo.xpi
zip -1 -r PrintButtonIsPrint@makyen.foo.xpi * -x@xpi.ignore
pause

这将删除 .xpi 文件的任何旧版本。然后它创建一个新的 .xpi 文件,使用 -1,最小压缩(访问速度比保存 space 更重要)并包含所有文件和子目录 ** 但忽略xpi.ignore 文本文件 -x@xpi.ignore 中的所有文件。使用忽略文件是因为目录中还有其他内容(例如 .git 目录、从编辑器自动创建的 .bak 文件等)。创建 .xpi 文件后,脚本会执行 pause 以便我可以验证包含了哪些文件、是否没有错误等,而不是让 window 消失并假设一切都很好。

我的xpi.ignore文件有点长,因为它积累了各种项目的内容,很少被清理掉:

*.com
*.class
*.dll
*.exe
*.o
*.so
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
*.log
*.sql
*.sqlite
*.svg
*/.DS_Store
*/.DS_Store?
*/._*
._*
*/.Spotlight-V100
.Spotlight-V100
*/.Trashes
.Trashes
*/ehthumbs.db
*/Thumbs.db
*.ORIG
*.bak
*OLD*
OLD/*
*/OLD/*
*.OLD
*.OLD[0-9]
*/OLD/*
*/OLD[0-9]/*
*.unknown
*.unknown[0-9]
*.updated
*.updated[0-9]
*/Copy *
*/OLD
*/OLD*
*/OLD[0-9]
*/OLD[0-9][0-9]
*/test/*
*/not in xpi/*
*/tmp
*.tmp
*/foo
*.foo
*checkpoint
.git
*/.git
.gitignore
*/.gitignore
xpi.ignore
mkclean.bat
mkclean.bat.DONTRUN
mkxpi.bat
*.xpi
*/devtools-toolbox-window.ico
*/devtools-webconsole.ico
*/JSConsoleWindow.ico
*/main-window.ico
*/places.ico
*/viewSource.ico

Installing extensions:

至于installing extensions (i.e. the .xpi file), it can be a simple matter of dragging and dropping it onto a Firefox window running the profile in which you desire it installed. For development/testing, you can have the extension be in a directory on your local drive by using a Firefox extension proxy file (create a file named as the extension's <em:id> in the profile's extensions directory containing one line with the complete path to the directory containing the extension's files). Depending on what your goal is (one profile, all profiles, all users, which OS, etc.), there are other options as to how to install extensions.

这个答案主要是从my answer here复制过来的。