Replace complete HTML with mozilla addon SDK

Is there a way to replace the complete HTML and add additional javascript files using the mozilla addon SDK?

With chrome, this can be done by running a script on "document_start", stop the window and replace the full HTML with an XHR response. I don't understand why it is so difficult, but I can live with it. As I understand it, the SDK addon has a page-mod which is about "running scripts in the context of web pages whose URL matches a given pattern." So in theory this should be done with the page-mod, but I haven't found any example that completely covers all HTML. In theory, window.stop and replacing the full HTML should work here too, but I cannot access the backend files from the context of the web page (frontend). Chrome does this through "web_accessible_resources" in the manifest and chrome.extension.getURL. By firefox, I cannot use anything related to the SDK addon interface,so self.data.url doesn't work ...

+1


source to share


1 answer


I tried to send the content of the file this way (since access to the addons file was denied by firefox from the frontend):

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;
        }
    });
}();

      

If I replace HTML with hello world then it works. So the HTML appears to be invalid, but I didn't get an error and the console displays an empty HTML skeleton (I got a blank page). The same index.html and main.js code works with the chrome plugin I want to use in firefox. The only thing the chrome plugin adds is that some js files are canceled, so of course they are not loaded before stopping the window. I tried to do the same, but it may not have worked, I don't know.

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);

      

The subject.cancel () object is executed by the some.js file. If I add a log:

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

      



Then "canceled" doesn't appear in the console, just "cancel, / some.js". I don't know if this is normal, but I have no error message.

Try this with a regular HTML webpage

<!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>

      

I got a line syntax error with an inexhaustible string which is even funnier. I think somehow the injector code is not working as expected if it contains javascript, so this is not an addon related issue I guess. If I use <\/script>

then it's ok but the console.log("loaded");

script won't run. On chrome it works, so I think this is the problem.

I added jquery to "contentScriptFile" and used $("html").html(html)

instead document.documentElement.innerHTML = html

. Now it runs scripts but still doesn't work as expected.

Added some fix for cancel ():

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

      

The cancellation appears to have the required status parameter, but it silently fails when it doesn't receive it. Now undoing files also works, but the plugin still doesn't work.: S

I think the injector I wrote works fine and the problem is with the HTML and js nested files. I do not intend to debug them (since $ .load uses eval, so it would be very difficult), I sent the code to the chrome plugin developers, maybe they can fix it.

0


source







All Articles