通过mozilla addon SDK

时间:2015-06-19 06:48:44

标签: javascript firefox-addon-sdk

有没有办法替换完整的HTML,并使用mozilla addon SDK添加其他javascript文件?

使用chrome可以通过在“document_start”运行脚本来完成,停止窗口并用XHR响应替换完整的HTML。我不明白为什么这么复杂,但我可以忍受。据我所知,addon SDK有一个page-mod模块,它关于“在URL匹配给定模式的网页上下文中运行脚本”。所以在理论上这应该用page-mod模块完成,但我没有找到任何完全覆盖整个HTML的例子。从理论上讲,window.stop和替换完整的HTML也应该在这里工作,但我无法从网页的上下文(前端)访问插件(后端)文件。通过chrome,这是通过清单和chrome.extension.getURL中的“web_accessible_resources”完成的。通过firefox我不能使用与前端SDK相关的任何东西,所以self.data.url不起作用......

1 个答案:

答案 0 :(得分:0)

我尝试以这种方式发送文件内容(因为firefox从前端拒绝了插件文件访问):

index.js

var pageMod = require("sdk/page-mod");
var data = require("sdk/self").data;

pageMod.PageMod({
    include: ["http://example.com/", "http://example.com/index.html"],
    contentScriptFile: "./inject.js",
    contentScriptWhen: "start",
    onAttach: function (worker){
        console.log("injector attached");
        worker.port.emit("inject", {
            "index.html": data.load("client/index.html"),
            "main.js": data.load("client/main.js")
        });
    }
});

inject.js

!function () {
    self.port.on("inject", function (files) {
        console.log("injector trigger");
        if (typeof hasRun == 'undefined') {
            console.log("injecting");
            hasRun = true;
            window.stop();
            var html = files["index.html"].replace("<script src=\"./main.js\"></script>", "<script>"+files["main.js"]+"</script>");
            document.documentElement.innerHTML = html;
        }
    });
}();

如果我用hello world替换HTML,那么它可以工作。因此HTML似乎无效,但我没有收到任何错误消息,控制台显示一个空的HTML骨架(我有一个空页面)。相同的index.html和main.js代码由chrome插件工作,我想在firefox中使用它。 chrome插件唯一额外的东西,一些js文件被取消,所以在停止窗口之前肯定没有加载它们。我试图做同样的事,但也许它不起作用,我不知道。

index.js

let { Ci, Cu } = require('chrome');

Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");

var observer = {
    QueryInterface: XPCOMUtils.generateQI([
        Ci.nsIObserver,
        Ci.nsISupportsWeakReference
    ]),

    observe: function (subject, topic, data) {
        if (topic == "http-on-opening-request" &&
            subject instanceof Ci.nsIHttpChannel) {
            var uri = subject.URI;
            if (uri.host == "example.com" && /some\.js/.test(uri.path))
                subject.cancel();
        }
    }
};

Services.obs.addObserver(observer, "http-on-opening-request", true);

subject.cancel()由some.js文件运行。如果我添加日志记录:

            console.log("cancelling", uri.path);
            subject.cancel();
            console.log("cancelled");

然后“取消”没有出现在控制台中,只是“取消,/ some.js”。我不知道这是否正常,但我没有收到任何错误信息。

通过常规HTML网页尝试此操作

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <script>
    //<![CDATA[
        !function (){
            window.stop();
            var html = '<!DOCTYPE html>\n<html>\n<head>\n    <meta charset="utf-8">\n</head>\n<body>\n  <script>console.log("loaded");</script>\ntext\n</body>\n</html>';
            document.documentElement.innerHTML = html;
        }();
    //]]>
    </script>
</body>
</html>

我得到了一个未终止的字符串文字语法错误,这甚至更有趣。我猜不知道如果它包含javascript,注入器代码不能正常工作,所以这不是我认为的插件相关问题。如果我使用<\/script>则可以,但console.log("loaded");脚本不会运行。通过chrome它会运行,所以这就是我认为的问题。

我将jquery添加到“contentScriptFile”并使用$("html").html(html)代替document.documentElement.innerHTML = html。它现在运行脚本,但仍然无法正常运行。

通过cancel()添加了一些修复:

let { Ci, Cu, Cr } = require('chrome');
//...
subject.cancel(Cr.NS_BINDING_ABORTED);

cancel似乎有一个必需的状态参数,但是当它没有得到它时它会无声地失败。现在取消文件也有效,但插件仍然在某处失败。 :S

我认为我编写的注入器工作完美,问题在于注入的HTML和js文件。我不打算调试它们(因为$ .load使用eval,所以它会非常困难),我将代码发送给chrome插件开发人员,也许他们可以以某种方式修复它。