Полезная информация

Список ответов на каверзные вопросы можно получить в FAQ-разделе форума.

№5104-12-2018 12:34:25

япогс
Участник
 
Группа: Members
Зарегистрирован: 08-03-2012
Сообщений: 272
UA: Firefox 52.0

Re: Озвучен срок прекращения работы XUL/XPCOM аддонов

Я вот чего-то не пойму! Мне что оставаться на XP или как? Не стоит обновляться и гнаться за последними версиями. Что тут за ретро ажиотаж?

Отсутствует

 

№5204-12-2018 12:58:31

Coroner
Участник
 
Группа: Members
Зарегистрирован: 29-10-2012
Сообщений: 3279
UA: Firefox 63.0

Re: Озвучен срок прекращения работы XUL/XPCOM аддонов

япогс пишет:

Мне что оставаться на XP или как?

Менять ОС лишь из-за одного браузера, по моему мнению, не стоит.

Отсутствует

 

№5304-12-2018 13:02:04

JustOff
Участник
 
Группа: Extensions
Зарегистрирован: 23-09-2015
Сообщений: 188
UA: Firefox 52.0

Re: Озвучен срок прекращения работы XUL/XPCOM аддонов

pag77 пишет:

Mozilla выполнила своё обещание - всё XUL-версии удалены

Classic Add-ons Archive - тут они сохранены

Отсутствует

 

№5405-12-2018 13:48:35

Kero
Участник
 
Группа: Members
Зарегистрирован: 09-11-2012
Сообщений: 180
UA: Firefox 52.0

Re: Озвучен срок прекращения работы XUL/XPCOM аддонов

plymouth
респект

Я вот чего-то не пойму! Мне что оставаться на XP или как? Не стоит обновляться и гнаться за последними версиями.

XP последняя дружелюбная к пользователю система,
7 повёрнутая к пользователям уже задом
10 послала пользователей на :tongue2:

JustOff

тут они сохранены

только инфа оних :(

Отредактировано Kero (05-12-2018 14:47:32)

Отсутствует

 

№5505-12-2018 14:03:37

JustOff
Участник
 
Группа: Extensions
Зарегистрирован: 23-09-2015
Сообщений: 188
UA: Firefox 52.0

Re: Озвучен срок прекращения работы XUL/XPCOM аддонов

Kero пишет:

JustOff пишет:

тут они сохранены

только инфа оних

Да, но все ссылки в этом каталоге ведут на независимое от AMO зеркало, откуда по-прежнему все можно скачать.

Отсутствует

 

№5605-12-2018 14:45:36

Kero
Участник
 
Группа: Members
Зарегистрирован: 09-11-2012
Сообщений: 180
UA: Firefox 52.0

Re: Озвучен срок прекращения работы XUL/XPCOM аддонов

JustOff а это вы сделали Classic Add-ons Archive  ?

Отсутствует

 

№5705-12-2018 15:10:16

JustOff
Участник
 
Группа: Extensions
Зарегистрирован: 23-09-2015
Сообщений: 188
UA: Firefox 52.0

Re: Озвучен срок прекращения работы XUL/XPCOM аддонов

Kero пишет:

JustOff а это вы сделали Classic Add-ons Archive  ?

Да.

Отсутствует

 

№5805-12-2018 15:26:10

Kero
Участник
 
Группа: Members
Зарегистрирован: 09-11-2012
Сообщений: 180
UA: Firefox 52.0

Re: Озвучен срок прекращения работы XUL/XPCOM аддонов

JustOff
ну тогда тоже респект :)

Отсутствует

 

№5905-12-2018 16:19:16

pag77
Участник
 
Группа: Extensions
Зарегистрирован: 20-03-2012
Сообщений: 1581
UA: Firefox 63.0

Re: Озвучен срок прекращения работы XUL/XPCOM аддонов

JustOff пишет:

Kero пишет: JustOff а это вы сделали Classic Add-ons Archive  ?Да.

да же на gHacks отметили :)
https://www.ghacks.net/2017/11/10/firef … s-archive/

Отсутствует

 

№6005-12-2018 20:44:39

япогс
Участник
 
Группа: Members
Зарегистрирован: 08-03-2012
Сообщений: 272
UA: Firefox 52.0

Re: Озвучен срок прекращения работы XUL/XPCOM аддонов

Coroner пишет:

Менять ОС лишь из-за одного браузера

Так ведь не работает нормально, нет поддержки новых видео форматов. Ютуб по двойному клику запускается. 52.9.0 уже не торт. Да и другие программы ушли вперед.

Kero пишет:

XP последняя дружелюбная к пользователю система

Возражать не буду, семерку видел поверхностно.  Мое: скачал установил и вперед без глубокой настройки. Без кастомизации и юзерхромизации.

Отсутствует

 

№6106-12-2018 00:20:55

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 869
UA: Firefox 52.0

Re: Озвучен срок прекращения работы XUL/XPCOM аддонов

JustOff пишет:

patches to run CAA in non-e10 window are welcome

Что-то стало интересно возможно ли это в принципе.
Изложу некоторые изыскания для Firefox, а ты, может, подхватишь.
Извиняюсь за сумбурное многословие.

чтиво
db.js
Заменил первый аргумент у NetUtil.asyncFetch(), ну просто потому, что пора.
Services.dirsvc.get("ProfD", ...) не работает в контентском процессе,
поэтому, на скорую руку, пробросил стилем, иначе вообще ничего не посмотреть,
даже точку с запятой не разреплейсил, а она может быть в путях.

Посмотрел, в принципе, само по себе, работает. Но операции
создания и удаления файлов не работают. Нужно у главного процесса просить.
Например сослаться в BSP/NSVO (то, что возвращает Cu.import()) на объект,
который создается ca-protocol.js (см. далее), а в нём метод чтоб заказать операцию.

Типа удалить, создать, получить путь до профиля.
Отправляется сообщение в главный процесс, слушается ответ, вызывается callback.
Всё это очень душно, не стал делать. А может и не нужно, всё это для старых версий,
где caa-страницы открываются в контентском процессе.


bootstrap.js
Тяп-ляп кое-что подпаял чтобы не доставало алертом и ошибками.
Ну и вышеупомянутый стиль с путём до профиля оттуда регистрируется.
Но главное — загрузка process script'а из функции startup() который отвечает за caa: протокол.


ca-protocol.js (новый файл)
Всё это была присказка, а теперь сказка.

С Firefox 54 в E10SUtils.jsm-переключатель, который отвечает за то,
в каком процессе будет открываться адрес, добавили проверку на nested URIs.

Таким образом, есть возможность заставить открываться caa-страницы
в главном процессе, даже из контентского. Для этого URI, возвращаемый
CAA nsIProtocolHandler'ом должен содержать соответстствующий nsINestedURI

Здесь подходит только адрес типа about: который,
с одной стороны, не содержит флагов, которые позволяют
открываться caa-адресам в контентском процессе,
а с другой стороны содержит флаги, которыми будет доволен nsIScriptSecurityManager

На Firefox 54 не проверял, но на Firefox 56 и Firefox 64, вроде, работает.
CAA-вкладки открываются как привилегированные и восстанавливаются после перезапуска.
И никаких контент-процессных ограничений.

Ну, то есть, если и у тебя подтвердится, то можно, например, декларировать,
что многопроцессность поддерживается с такой-то (54?) версии Firefox,
если не хочется перегонять межпроцессные сообщения туда-сюда для более старых версий.

Хотя, можно попробовать переопределить сам E10SUtils-переключатель,
если счесть такое позволительным.

Вобщем попробуй, если заинтересовало. Коды далее.

коды
db.js

Выделить код

Код:

"use strict";
let EXPORTED_SYMBOLS = ["DB"];

var Cc = Components.classes, Ci = Components.interfaces, Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");

function copyDataURLToFile(document, url, file, callback) {
  //NetUtil.asyncFetch(url, function(istream) {
  NetUtil.asyncFetch({uri: url, loadUsingSystemPrincipal: true}, function(istream) {
    let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
                  createInstance(Ci.nsIFileOutputStream);
    ostream.init(file, -1, -1, Ci.nsIFileOutputStream.DEFER_OPEN);
    NetUtil.asyncCopy(istream, ostream, function(result) {
      callback && callback(file, result, document);
    });
  });
}

function showMessage(document, msg, style) {
    let div = document.createElement("div");
    div.className = style;
    div.appendChild(document.createTextNode(msg));
    let page = document.getElementById("page");
    page.appendChild(div);
}

let DB = {

    db: null,

    openDB: function(dbname, document) {
        //let dir = Services.dirsvc.get("ProfD", Ci.nsIFile); dir.append("ca-archive");

        var profDirPath = document.defaultView
            .getComputedStyle(document.documentElement)
            .getPropertyValue("--profile-directory");

        let dir = FileUtils.File(profDirPath); dir.append("ca-archive");
        try {
            let storageService = Cc["@mozilla.org/storage/service;1"].getService(Ci.mozIStorageService);
            let dbFile = dir.clone(); dbFile.append(dbname);
            if (dbFile.exists() && dbFile.fileSize > 0) {
                this.db = storageService.openDatabase(dbFile);
            } else {
                if (!dir.exists()) {
                    showMessage(document, "Performing initial database provisioning ...", "db-warning ok");
                    throw "Init";
                } else {
                    throw "CA Archive database has just been updated, not ready or corrupted!";
                }
            }
            return true;
        } catch (e) {
            if (e != "Init") {
                Cu.reportError(e);
                showMessage(document, e, "db-warning");
                showMessage(document, "Trying to (re)provision database, please wait ...", "db-warning");
            }
            let tmpFile = FileUtils.getFile("TmpD", ["ca-archive.tmp"]);
            tmpFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
            let src = Services.io.newURI("chrome://ca-archive/content/db/" + dbname, null, null);
            copyDataURLToFile(document, src, tmpFile, function(file, result, document) {
                try {
                    if (result == 0 && file.exists()) {
                        if (dir.exists()) {
                            dir.remove(true);
                        }
                        dir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
                        tmpFile.moveTo(dir, dbname);
                        showMessage(document, "Database has been processed successfully!", "db-warning ok");
                        showMessage(document, "Please reload the page.", "db-warning ok");
                    } else {
                        throw "CA Archive database Fatal Error!";
                    }
                } catch (e) {
                    Cu.reportError(e);
                    showMessage(document, e, "db-warning bad");
                    showMessage(document, "Try to reinstall CA Archive.", "db-warning bad");
                }
            });
            return false;
        }
    },

    closeDB: function() {
        this.db.close();
    }

};

bootstrap.js

Выделить код

Код:

"use strict";

var TEST = true;

var {classes: Cc, interfaces: Ci, manager: Cm, results: Cr, Constructor: CC, utils: Cu} = Components;
Cm.QueryInterface(Ci.nsIComponentRegistrar);

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

const SCHEME = "caa";
const CAA_URL ="chrome://ca-archive/content/ca-archive.html";
const CAA_URI = Services.io.newURI(CAA_URL, null, null);

if (!TEST)
    var nsIURI = CC("@mozilla.org/network/simple-uri;1", "nsIURI");

const ff47plus = (Services.vc.compare(Services.appinfo.version, 47) > 0);

const CAA_MODULES = [
    "chrome://ca-archive/content/about.js",
    "chrome://ca-archive/content/addon.js",
    "chrome://ca-archive/content/db.js",
    "chrome://ca-archive/content/epl.js",
    "chrome://ca-archive/content/list.js",
    "chrome://ca-archive/content/tcloud.js",
    "chrome://ca-archive/content/versions.js"
];

let factory, storageHost, gWindowListener = null, branch = "extensions.ca-archive.";

let styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
let styleSheetURI = Services.io.newURI("chrome://ca-archive/skin/button.css", null, null);

function $(node, childId) {
    if (node.getElementById) {
        return node.getElementById(childId);
    } else {
        return node.querySelector("#" + childId);
    }
}

let button = {
    meta : {
        id : "ca-archive-button",
        label : "Classic Add-ons Archive",
        tooltiptext : "Classic Add-ons Archive",
        class : "toolbarbutton-1 chromeclass-toolbar-additional"
    },
    install : function (w) {
        let doc = w.document;
        let b = doc.createElement("toolbarbutton");
        for (let a in this.meta) {
            b.setAttribute(a, this.meta[a]);
        }
        b.style.listStyleImage = 'url("chrome://ca-archive/skin/button.png")';

        let toolbox = $(doc, "navigator-toolbox");
        toolbox.palette.appendChild(b);

        let {toolbarId, nextItemId} = this.getPrefs(),
            toolbar = toolbarId && $(doc, toolbarId),
            nextItem = toolbar && $(doc, nextItemId);
        if (toolbar) {
            if (nextItem && nextItem.parentNode && nextItem.parentNode.id.replace("-customization-target", "") == toolbarId) {
                toolbar.insertItem(this.meta.id, nextItem);
            } else {
                let ids = (toolbar.getAttribute("currentset") || "").split(",");
                nextItem = null;
                for (let i = ids.indexOf(this.meta.id) + 1; i > 0 && i < ids.length; i++) {
                    nextItem = $(doc, ids[i])
                    if (nextItem) {
                        break;
                    }
                }
                toolbar.insertItem(this.meta.id, nextItem);
            }
            if (toolbar.getAttribute("collapsed") == "true") {
                try { w.setToolbarVisibility(toolbar, true); } catch(e) {}
            }
        }
        return b;
    },
    onCustomize : function(e) {
        try {
            let ucs = Services.prefs.getCharPref("browser.uiCustomization.state");
            if ((/\"nav\-bar\"\:\[.*?\"ca\-archive\-button\".*?\]/).test(ucs)) {
                Services.prefs.getBranch(branch).setCharPref("toolbarId", "nav-bar");
            } else {
                button.setPrefs(null, null);
            }
        } catch(e) {}
    },
    afterCustomize : function (e) {
        let toolbox = e.target,
            b = $(toolbox.parentNode, button.meta.id),
            toolbarId, nextItemId;
        if (b) {
            let parent = b.parentNode,
                nextItem = b.nextSibling;
            if (parent && (parent.localName == "toolbar" || parent.classList.contains("customization-target"))) {
                toolbarId = parent.id;
                nextItemId = nextItem && nextItem.id;
            }
        }
        button.setPrefs(toolbarId, nextItemId);
    },
    getPrefs : function () {
        let p = Services.prefs.getBranch(branch);
        return {
            toolbarId : p.getCharPref("bar"),
            nextItemId : p.getCharPref("before")
        };
    },
    setPrefs : function (toolbarId, nextItemId) {
        let p = Services.prefs.getBranch(branch);
        p.setCharPref("bar", toolbarId == "nav-bar-customization-target" ? "nav-bar" : toolbarId || "");
        p.setCharPref("before", nextItemId || "");
    }
};

let menuitem = {
    meta : {
        id : "ca-archive-menu",
        label : "Classic Add-ons Archive",
        class : "menuitem-iconic"
    },
    install : function (w) {
        let doc = w.document;
        let m = doc.createElement("menuitem");
        for (let a in this.meta) {
            m.setAttribute(a, this.meta[a]);
        }
        m.style.listStyleImage = 'url("chrome://ca-archive/skin/button.png")';

        let menu;
        if (Services.appinfo.name == "SeaMonkey") {
            menu = $(doc, "taskPopup");
        } else {
            menu = $(doc, "menu_ToolsPopup");
        }
        menu.insertBefore(m, null);
        return m;
    }
};

let caaIn = function (w) {
    let b = button.install(w);
    let m = menuitem.install(w);

    return {
        init : function () {
            w.addEventListener("customizationchange", button.onCustomize, false);
            w.addEventListener("aftercustomization", button.afterCustomize, false);
            b.addEventListener("command", this.run, false);
            m.addEventListener("command", this.run, false);
        },
        done : function () {
            w.removeEventListener("customizationchange", button.onCustomize, false);
            w.removeEventListener("aftercustomization", button.afterCustomize, false);
            b.removeEventListener("command", this.run, false);
            b.parentNode.removeChild(b);
            b = null;
            m.removeEventListener("command", this.run, false);
            m.parentNode.removeChild(m);
            m = null;
        },
        run : function () {
            function isRemote (win) {
                let loadContext = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsILoadContext);
                return loadContext.useRemoteTabs;
            }

            if (TEST) isRemote = () => false;

            let e10s = isRemote(Services.wm.getMostRecentWindow("navigator:browser"));
            if (e10s && Services.appinfo.name != "Waterfox") {
                Services.prompt.alert(null, "Classic Add-ons Archive", "Multi-process mode is not supported now,\nplease disable it and restart " + Services.appinfo.name + ".");
                return;
            }
            let isOpen = false, ne10win = null;
            let winenu = Services.wm.getEnumerator("navigator:browser");
            loop: while (winenu.hasMoreElements()) {
                let window = winenu.getNext().QueryInterface(Ci.nsIDOMWindow);
                for (let tab of window.gBrowser.tabs) {
                    if (tab.linkedBrowser.currentURI.scheme == "caa") {
                        window.focus();
                        window.gBrowser.selectedTab = tab;
                        isOpen = true;
                        break loop;
                    }
                }
                if (e10s && ne10win === null) {
                    if (!isRemote(window)) {
                        ne10win = window;
                    }
                }
            }
            if (!isOpen) {
                let mrw = Services.wm.getMostRecentWindow("navigator:browser");
                let url = Services.prefs.getBranch(branch).getCharPref("url");
                if (!e10s) {

                    if (TEST) {
                        var gb = mrw.gBrowser;
                        gb.selectedTab = (gb.addTrustedTab || gb.addTab).call(gb, url);
                    }
                    else
                        mrw.gBrowser.selectedTab = mrw.gBrowser.addTab(url);
                } else {
                    if (ne10win === null) {
                        mrw.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no,non-remote", url);
                    } else {
                        ne10win.focus();
                        ne10win.gBrowser.selectedTab = ne10win.gBrowser.addTab(url);
                    }
                }
                if (url == "caa:about") {
                    Services.prefs.getBranch(branch).setCharPref("url", "caa:");
                }
            }
        }
    };
};

function BrowserWindowObserver(handlers) {
    this.handlers = handlers;
}

BrowserWindowObserver.prototype = {
    observe: function (aSubject, aTopic, aData) {
        if (aTopic == "domwindowopened") {
            aSubject.QueryInterface(Ci.nsIDOMWindow).addEventListener("load", this, false);
        } else if (aTopic == "domwindowclosed") {
            if (aSubject.document.documentElement.getAttribute("windowtype") == "navigator:browser") {
                this.handlers.onShutdown(aSubject);
            }
        }
    },
    handleEvent: function (aEvent) {
        let aWindow = aEvent.currentTarget;
        aWindow.removeEventListener(aEvent.type, this, false);

        if (aWindow.document.documentElement.getAttribute("windowtype") == "navigator:browser") {
            this.handlers.onStartup(aWindow);
        }
    }
};

function browserWindowStartup (aWindow) {
    aWindow["ca-archive"] = caaIn(aWindow);
    aWindow["ca-archive"].init()
}

function browserWindowShutdown (aWindow) {
    aWindow["ca-archive"].done();
    delete aWindow["ca-archive"];
}

function CAAProtocolHandler() {}

CAAProtocolHandler.prototype = Object.freeze({
    classDescription: "CAA Protocol Handler",
    contractID: "@mozilla.org/network/protocol;1?name=" + SCHEME,
    classID: Components.ID('{f0700cf0-b198-11e7-8f1a-0800200c9a66}'),
    QueryInterface:
        TEST ? (
            "generateQI" in XPCOMUtils ? XPCOMUtils : ChromeUtils
        ).generateQI([Ci.nsIProtocolHandler])

        : XPCOMUtils.generateQI([Ci.nsIProtocolHandler]),

    scheme: SCHEME,
    defaultPort: -1,

    allowPort: function(port, scheme) {
        return false;
    },

    protocolFlags: Ci.nsIProtocolHandler.URI_NORELATIVE |
                   Ci.nsIProtocolHandler.URI_NOAUTH |
                   Ci.nsIProtocolHandler.URI_LOADABLE_BY_ANYONE |
                   Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE |
                   Ci.nsIProtocolHandler.URI_OPENING_EXECUTES_SCRIPT,

    newURI: function(aSpec, aOriginCharset, aBaseURI) {
        if (aBaseURI && aBaseURI.scheme == SCHEME) {
            if (aSpec != "/") {
                return Services.io.newURI(aSpec, aOriginCharset, CAA_URI);
            } else {
                return CAA_URI;
            }
        }

        let rv = new nsIURI();
        rv.spec = aSpec;
        return rv;
    },

    newChannel: function(aURI) {
        return this.newChannel2(aURI, null);
    },

    newChannel2: function(aURI, aSecurity_or_aLoadInfo) {
        let channel;
        if (aSecurity_or_aLoadInfo || ff47plus) {
            let uri = Services.io.newURI(CAA_URL, null, null);
            channel = Services.io.newChannelFromURIWithLoadInfo(uri, aSecurity_or_aLoadInfo);
        } else {
            channel = Services.io.newChannel(CAA_URL, null, null);
        }
        channel.originalURI = aURI;
        return channel;
    }
});

function Factory(component) {
    this.createInstance = function(outer, iid) {
        if (outer) {
            throw Cr.NS_ERROR_NO_AGGREGATION;
        }
        return new component();
    };
    this.register = function() {
        Cm.registerFactory(component.prototype.classID, component.prototype.classDescription, component.prototype.contractID, this);
    };
    this.unregister = function() {
        Cm.unregisterFactory(component.prototype.classID, this);
    };
    Object.freeze(this);
    this.register();
}

let httpObserver = {
    observe: function(subject, topic, data) {
        if (topic == "http-on-modify-request") {
            subject.QueryInterface(Ci.nsIHttpChannel);
            if (subject.URI.host == "web.archive.org") {
                if (/^\/web\/.+?\/(addons\.mozilla\.org\/.+?\/more|addons\.cdn\.mozilla\.net\/.+?\/loading-more\.gif.*?|addons-amo\.cdn\.mozilla\.net\/amo-.+?\.js)$/.test(subject.URI.path)) {
                    subject.cancel(Cr.NS_BINDING_ABORTED);
                }
            }
        } else if (topic == "http-on-examine-response" || topic == "http-on-examine-cached-response") {
            subject.QueryInterface(Ci.nsIHttpChannel);
            if (subject.URI.host == storageHost) {
                if (/origin=caa&action=install$/.test(subject.URI.path)) {
                    subject.setResponseHeader("Content-Disposition", "", false);
                } else if (/origin=caa&action=download$/.test(subject.URI.path)) {
                    subject.setResponseHeader("Content-Disposition", "attachment", false);
                }
            } else if (subject.URI.host == "ca-archive.biz.tm") {
                if (subject.responseStatus == "302" && /^\/storage\//.test(subject.URI.path)) {
                    let redirect;
                    if ((redirect = /^https?:\/\/(.+?)\//.exec(subject.getResponseHeader("Location"))) !== null) {
                        storageHost = redirect[1];
                    }
                }
            }
        }
    },
    QueryInterface: function(aIID) {
        if (aIID.equals(Ci.nsIObserver) || aIID.equals(Ci.nsISupports)) {
            return this;
        } else {
            throw Cr.NS_NOINTERFACE;
        }
    },
    register: function() {
        Services.obs.addObserver(this, "http-on-modify-request", false);
        Services.obs.addObserver(this, "http-on-examine-response", false);
        Services.obs.addObserver(this, "http-on-examine-cached-response", false);
    },
    unregister: function() {
        Services.obs.removeObserver(this, "http-on-modify-request");
        Services.obs.removeObserver(this, "http-on-examine-response");
        Services.obs.removeObserver(this, "http-on-examine-cached-response");
    }
}

var profDirSheetURI = Services.io.newURI("data:text/css," + encodeURIComponent(`
    @-moz-document url-prefix("caa:") {
        :root {
            --profile-directory:${
                Services.dirsvc.get("ProfD", Ci.nsIFile).path
            };
        }
    }
`), null, null);

function startup(data, reason) {
    if (!styleSheetService.sheetRegistered(styleSheetURI, styleSheetService.USER_SHEET)) {
        styleSheetService.loadAndRegisterSheet(styleSheetURI, styleSheetService.USER_SHEET);
        styleSheetService.loadAndRegisterSheet(profDirSheetURI, styleSheetService.USER_SHEET);
    }

    if (TEST)
        Services.ppmm.loadProcessScript("chrome://ca-archive/content/ca-protocol.js", true);
    else
        factory = new Factory(CAAProtocolHandler);

    let defaultBranch = Services.prefs.getDefaultBranch(branch);
    defaultBranch.setCharPref("bar", "nav-bar");
    defaultBranch.setCharPref("before", "");
    defaultBranch.setCharPref("url", "caa:about");

    httpObserver.register();

    gWindowListener = new BrowserWindowObserver({
        onStartup: browserWindowStartup,
        onShutdown: browserWindowShutdown
    });
    Services.ww.registerNotification(gWindowListener);
    
    let winenu = Services.wm.getEnumerator("navigator:browser");
    while (winenu.hasMoreElements()) {
        browserWindowStartup(winenu.getNext());
    }
}

function shutdown(data, reason) {
    if (reason == APP_SHUTDOWN) return;

    Services.ww.unregisterNotification(gWindowListener);
    gWindowListener = null;

    httpObserver.unregister();

    let winenu = Services.wm.getEnumerator("navigator:browser");
    while (winenu.hasMoreElements()) {
        browserWindowShutdown(winenu.getNext());
    }

    if (TEST) {
        Services.ppmm.removeDelayedProcessScript("chrome://ca-archive/content/ca-protocol.js");
        Services.ppmm.broadcastAsyncMessage("CAAHandler:DestroyHandler");
    }
    else
        factory.unregister();

    if (reason == ADDON_UNINSTALL) {
        try {
            let dir = Services.dirsvc.get("ProfD", Ci.nsIFile); dir.append("ca-archive");
            if (dir.exists()) {
                dir.remove(true);
            }
        } catch (e) {}
    }

    if (styleSheetService.sheetRegistered(styleSheetURI, styleSheetService.USER_SHEET)) {
        styleSheetService.unregisterSheet(styleSheetURI, styleSheetService.USER_SHEET);
        styleSheetService.unregisterSheet(profDirSheetURI, styleSheetService.USER_SHEET);
    }

    CAA_MODULES.forEach(Cu.unload, Cu);
}

function install(data, reason) {}
function uninstall(data, reason) {}

ca-protocol.js

Выделить код

Код:

((
    {classes: Cc, interfaces: Ci, manager: Cm, results: Cr, utils: Cu},
    {Services, XPCOMUtils}, CAAHandler = function(url) {
        this.uri = Services.io.newURI(this.url = url, null, null);
    }
) => (CAAHandler.prototype = {

    topic: "content-child-shutdown",
    message: "CAAHandler:DestroyHandler",
    ff47plus: parseFloat(Services.appinfo.platformVersion) >= 47,

    init() {
        Cm.QueryInterface(Ci.nsIComponentRegistrar);
        this.observe = this.receiveMessage = () => {
            Services.obs.removeObserver(this, this.topic);
            removeMessageListener(this.message, this);
            this.unregister();
        }
        Services.obs.addObserver(this, this.topic, false);
        addMessageListener(this.message, this);
        this.register();
    },
    register() {
        Cm.registerFactory(this.aClassID, this.aClassDescription, this.aContractID, this);
        Cm.registerFactory(this.pClassID, this.pClassDescription, this.pContractID, this);
    },
    unregister() {
        Cm.unregisterFactory(this.aClassID, this);
        Cm.unregisterFactory(this.pClassID, this);
    },

    createInstance(outer, iid) {
        if (outer) throw Cr.NS_ERROR_NO_AGGREGATION;

        if (iid.equals(Ci.nsIProtocolHandler)) return new CAAHandler(
            "chrome://ca-archive/content/ca-archive.html"
        );
        if (iid.equals(Ci.nsIAboutModule)) return new CAAHandler(
            "data:text/plain;charset=utf-8,CAA"
        );
        throw Cr.NS_ERROR_NO_INTERFACE;
    },
    QueryInterface: (
        "generateQI" in XPCOMUtils ? XPCOMUtils : ChromeUtils
    ).generateQI([
        Ci.nsIProtocolHandler, Ci.nsIAboutModule
    ]),

    pClassDescription: "CAA Protocol Handler",
    pContractID: "@mozilla.org/network/protocol;1?name=caa",
    pClassID: Components.ID("{f0700cf0-b198-11e7-8f1a-0800200c9a66}"),

    scheme: "caa",
    defaultPort: -1,
    allowPort: () => false,
    protocolFlags:
        Ci.nsIProtocolHandler.URI_NOAUTH |
        Ci.nsIProtocolHandler.URI_NORELATIVE |
        Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE |
        Ci.nsIProtocolHandler.URI_LOADABLE_BY_ANYONE |
        Ci.nsIProtocolHandler.URI_OPENING_EXECUTES_SCRIPT,

    newURI(aSpec, aOriginCharset, aBaseURI) {
        if (aBaseURI && aBaseURI.scheme == this.scheme) {
            if (aSpec != "/") {
                return Services.io.newURI(aSpec, aOriginCharset, this.uri);
            } else {
                return this.uri;
            }
        }
        return this.makeURI(aSpec);
    },
    makeURI(spec) {
        if ("mutate" in this.uri)
            var mutator = Services.io.newURI("view-source:about:caa").QueryInterface(Ci.nsINestedURI),
            makeURI = spec => mutator.mutate().setSpec(spec).finalize();

        else {
            var netUtil = Cc['@mozilla.org/network/util;1'].getService(Ci.nsINetUtil);
            var notRemoteAboutURI = Services.io.newURI("about:caa", null, null);
            notRemoteAboutURI = netUtil.toImmutableURI(notRemoteAboutURI);

            var makeURI = spec => {
                var uri = netUtil.newSimpleNestedURI(notRemoteAboutURI);
                uri.spec = spec;
                return uri;
            }
        }
        return (Object.getPrototypeOf(this).makeURI = makeURI)(spec);
    },

    aClassDescription: "CAA About Module",
    aContractID: "@mozilla.org/network/protocol/about;1?what=caa",
    aClassID: Components.ID("{bc221903-f3e4-4bdc-888d-ceb629f96df4}"),

    getURIFlags: () =>
        Ci.nsIAboutModule.MAKE_LINKABLE |
        Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT,

    newChannel(aURI) {
        return this.newChannel2(aURI, null);
    },
    newChannel2(aURI, aSecurity_or_aLoadInfo) {
        var channel = aSecurity_or_aLoadInfo || this.ff47plus
            ? Services.io.newChannelFromURIWithLoadInfo(this.uri, aSecurity_or_aLoadInfo)
            : Services.io.newChannel(this.url, null, null);
        channel.originalURI = aURI;
        return channel;
    }
}).init())(Components, Components.utils.import("resource://gre/modules/Services.jsm", {}));

Отсутствует

 

№6206-12-2018 17:59:31

JustOff
Участник
 
Группа: Extensions
Зарегистрирован: 23-09-2015
Сообщений: 188
UA: Firefox 52.0

Re: Озвучен срок прекращения работы XUL/XPCOM аддонов

Dumby пишет:

Изложу некоторые изыскания для Firefox, а ты, может, подхватишь.

Спасибо, я экспериментировал приблизительно похожим образом, но безглючного варианта, увы, так и не получилось.

всяческие подробности
Я точно так же вынес поддержку протокола в отдельный модуль для загрузки через loadProcessScript, а потом затосковал от необходимости переделывать всю логику работы с базой на клиент-сервер через сообщения. Ну вот как-то вот вообще нет желания этим заниматься, от слова совсем.

Дальше добрался до E10SUtils.jsm и попытался подменить canLoadURIInProcess, но так и не придумал как это нормально сделать. А вот до идеи с nsINestedURI не дошел, т.к. ковырял ESR52, в котором этой логики еще нет, хотя, если честно, я и сейчас не до конца понимаю код makeURI в котором вы это сделали.

Впрочем, похоже проблемы этим не исчерпываются: в вашем варианте у меня сами страницы caa:* отображаются успешно, но при попытке загрузить или установить дополнение содержимое текущей страницы просто молча исчезает и как-то даже никаких идей какого-такого собственно.

Отсутствует

 

№6307-12-2018 15:10:13

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 869
UA: Firefox 52.0

Re: Озвучен срок прекращения работы XUL/XPCOM аддонов

JustOff

скрытый текст

не до конца понимаю код makeURI

Попробую объяснить.
Нужно создать функцию, которая вернёт nested URI.

Для этого проверяем есть ли у какого-нибудь URI метод "mutate",
который добавили в Firefox 59, а проверяем потому,
что всё в том же Firefox 59 выпилили nsINetUtil.newSimpleNestedURI()

Если метод "mutate" есть

Преподготовка: создаём URI с адресом "view-source:about:caa"
(это nested URI у которого innerURI будет "about:caa").
У него будем вызвать mutate() чтобы получить nsIURIMutator.

Функция: получаем мутатор, setSpec() установит адрес и вернёт этот же мутатор,
а finalize() вернёт свежеиспечённый URI (у которого innerURI останется "about:caa").
Его и возвращаем.

Если метода "mutate" нет

Преподготовка: получаем nsINetUtil, создаём URI с адресом "about:caa"
и пропускаем через nsINetUtil.toImmutableURI().
Полученный URI (это будет будущий innerURI) понадобится как аргумент
для nsINetUtil.newSimpleNestedURI().

Функция: вызываем newSimpleNestedURI() с подготовленным URI,
вернется пустая болванка с нужным innerURI.
Устанавливаем spec, возвращаем новорождённый URI.

Всё. Все инстанции созданы, функция определена.

Теперь (при первом вызове) заменяем в прототипе метод makeURI
на нашу созданную функцию, вызываем её и возвращаем результат вызова.
Это что-то типа lazy getter'а.

Ну вот, как-то так.

добрался до E10SUtils.jsm и попытался подменить canLoadURIInProcess, но так и не придумал как это нормально сделать
...
содержимое текущей страницы просто молча исчезает и как-то даже никаких идей какого-такого собственно

У меня есть предположение, что это всё тот же E10SUtils-переключатель так выкрутасничает.
Прощай caa-страница из главного процесса, здравствуй about:blank из дочернего.

А подменить, давай я пропробую, чисто теоретически, сделать набросок подменялки,
а ты скажешь, полный отстой или в этом что-то есть.

CAAHandler.prototype.init()

Выделить код

Код:

    init() {
        var isTargetLink = url =>
            url.startsWith("https://ca-archive.biz.tm/storage/") &&
            Services.focus.focusedWindow &&
            Services.focus.focusedWindow.location &&
            Services.focus.focusedWindow.location.href.startsWith("caa:");
        try {
            var {E10SUtils} = Cu.import("resource:///modules/E10SUtils.jsm", {});
        } catch(ex) {
            var {E10SUtils} = Cu.import("resource://gre/modules/E10SUtils.jsm", {}); // Firefox 59+
        }
        var method, key = "getRemoteTypeForURI"; // Firefox 53+
        if (key in E10SUtils)
            if ("getRemoteTypeForURIObject" in E10SUtils) // Firefox 54+
                method = E10SUtils[key = "getRemoteTypeForURIObject"],
                E10SUtils[key] = function(uri) {
                    return uri.schemeIs("caa:") || isTargetLink(uri.spec)
                        ? E10SUtils.NOT_REMOTE : method.apply(this, arguments);
                }
            else
                method = E10SUtils[key],
                E10SUtils[key] = function(url) {
                    return url.startsWith("caa:") || isTargetLink(url)
                        ? E10SUtils.NOT_REMOTE : method.apply(this, arguments);
                }
        else
            method = E10SUtils[key = "canLoadURIInProcess"],
            E10SUtils[key] = function(url, process) {
                if (url.startsWith("caa:"))
                    return process == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
                if (isTargetLink(url))
                    return true;
                return method.apply(this, arguments);
            }

        Cm.QueryInterface(Ci.nsIComponentRegistrar);
        this.observe = this.receiveMessage = () => {
            E10SUtils[key] = method;

            Services.obs.removeObserver(this, this.topic);
            removeMessageListener(this.message, this);
            this.unregister();
        }
        Services.obs.addObserver(this, this.topic, false);
        addMessageListener(this.message, this);
        this.register();
    },

Отсутствует

 

Board footer

Powered by PunBB
Modified by Mozilla Russia
Copyright © 2004–2011 Mozilla Russia
Язык отображения форума: [Русский] [English]