Заменете целия HTML с mozilla addon SDK

Има ли начин да замените целия HTML и да добавите допълнителни javascript файлове с mozilla addon SDK?

С chrome това може да стане чрез стартиране на скрипта в "document_start", спиране на прозореца и замяна на пълния HTML с XHR отговор. Не разбирам защо това е толкова сложно, но мога да живея с това. Доколкото разбирам, addon SDK има модул за модифициране на страници, който е за "изпълняване на скриптове в контекста на уеб страници, чийто URL адрес съответства на даден шаблон." Така че на теория това трябва да се направи с модула page-mod, но не намерих нито един пример, който напълно да отменя целия HTML. На теория window.stop и замяната на пълния HTML трябва да работят и тук, но не мога да осъществя достъп до файловете на добавките (backend) от контекста на уеб страницата (frontend). Чрез chrome това се прави чрез „web_accessible_resources“ в манифеста и chrome.extension.getURL. Чрез firefox не мога да използвам нищо, свързано с SDK на добавките чрез интерфейс, така че self.data.url не работи...


person inf3rno    schedule 19.06.2015    source източник


Отговори (1)


Опитах се да изпратя съдържанието на файла по този начин (тъй като достъпът до файла на добавката беше отказан от 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")
        });
    }
});

инжектиране.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;
        }
    });
}();

Ако заменя HTML с hello world, тогава работи. Така че 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 изглежда има задължителен параметър за състояние, но тихо се проваля, когато не го получи. Сега анулирането на файлове също работи, но плъгинът все още се проваля някъде. :С

Мисля, че инжекторът, който написах, работи перфектно и проблемът е в инжектираните HTML и js файлове. Нямам намерение да ги дебъгвам (тъй като $.load използва eval, така че би било много трудно), изпратих кода на разработчиците на плъгини за chrome, може би те могат да го поправят по някакъв начин.

person inf3rno    schedule 19.06.2015