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

Хотите узнать больше о расширениях? Посмотрите ролики, рассказывающие о работе с расширениями Firefox.

№1315118-03-2019 17:52:16

drage2
Забанен
 
Группа: Members
Откуда: Донецк
Зарегистрирован: 23-11-2017
Сообщений: 392
UA: Firefox 67.0

Re: Custom Buttons

Dumby
Нема речи....Круто....очень круто. Первый раз сдаюсь, bootstrap-loader.js - подходит идеально для 67...Туда же и префы от Mozilla.cfg вставил ... Респект,однозначно!
Это ж ночнуха и телеметрию зарубить можно только через преф Mozilla.cfg , а тут код вписался идеально...

Отредактировано drage2 (18-03-2019 18:12:43)

Отсутствует

 

№1315218-03-2019 17:56:27

vitalii201
Участник
 
Группа: Members
Зарегистрирован: 24-03-2011
Сообщений: 586
UA: Firefox 65.0

Re: Custom Buttons

Dumby, спасибо.

Отредактировано vitalii201 (19-03-2019 09:08:09)

Отсутствует

 

№1315319-03-2019 00:37:17

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

Re: Custom Buttons

leex пишет:

Можно ли сделать одну загрузку без Сtrl+F5 если  "Ошибка искажения содержимого" не обнаружена?

Если «Ошибка искажения содержимого» это лисья страница,
то можно попробовать как-то так, а если нет, то вопрос, увы, не ко мне.

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

Выделить код

Код:

(frameScript => {
    this._handleClick = () => addTab("http://mail.google.com/mail/#i");
    this.oncontextmenu = e => e.ctrlKey || e.shiftKey || addTab("https://mail.google.com/mail/u/0/#sent") || false;
    var addTab = url => {
        var tab = gBrowser.selectedTab = gBrowser.addTab(url, {
            triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()
        });
        var browser = tab.linkedBrowser;
        setTimeout(function wait() {
            if(browser.currentURI.spec == "about:blank" || browser.webProgress.isLoadingDocument)
                setTimeout(wait, 25);
            else
                browser.messageManager.loadFrameScript(frameScript, false);
        }, 0);
    }
})(
    "data:,content.document.documentURI.startsWith('about:neterror')&&(wn=>wn.reload(wn.LOAD_FLAGS_BYPASS_PROXY"
    + "|wn.LOAD_FLAGS_BYPASS_CACHE))(docShell.QueryInterface(Components.interfaces.nsIWebNavigation))"
);


vitalii201 пишет:

скачивается custom_buttons-0.0.7.0.0 с расширением .3-FX-PAXMOD_XPI  в 14КБ )

Ну не знаю, посетил страницу по ссылке,
на странице нажал ссылку-кнопку [ DOWNLOAD (188.6 KB) ],

появилось окошко "Открытие «custom_buttons-0.0.7.0.0.3-fx-paxmod.xpi»",
(<radiogroup> в положении "Сохранить файл")

в окошке нажал OK, выбрал папку для сохранения и...
скачался custom_buttons-0.0.7.0.0.3-fx-paxmod.xpi размером 184КБ (на диске 188КБ).
Это тупик.

Отсутствует

 

№1315419-03-2019 00:50:09

leex
Участник
 
Группа: Members
Зарегистрирован: 24-03-2011
Сообщений: 244
UA: Firefox 50.0

Re: Custom Buttons

Dumby
Отлично! Все работает хорошо
Спасибо вам за это решение :)

PS

В профиле лисы лежит файл serviceworker.txt Если его удалить или очистить, то страница гмаил загружается без проблем.
Но он все равно появляется и перезаписывается.  ФФ56

Отредактировано leex (19-03-2019 01:41:12)

Отсутствует

 

№1315519-03-2019 14:22:26

func4ptch4
Участник
 
Группа: Members
Зарегистрирован: 03-05-2018
Сообщений: 125
UA: Firefox 65.0

Re: Custom Buttons

leex
Создай временно как пустой файл, и поставь только чтение... потом найдешь решение.

Вот что нашел:

Выделить код

Код:

// Отключает Service Worker API, позволяющее сайтам запускать скрипты, которые могут заниматься
// различной сомнительной самодеятельностью (примеры по ссылкам ниже) в фоновом режиме, даже
// если у пользователя не открыто ни одной вкладки этого сайта.
// Посмотреть и удалить установленные сайтами Service Workers можно через about:serviceworkers
// https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API#Other_use_case_ideas
// https://github.com/slightlyoff/ServiceWorker
// https://serviceworke.rs/
pref("dom.serviceWorkers.enabled", false);
pref("dom.serviceWorkers.interception.enabled", false);
pref("dom.serviceWorkers.interception.opaque.enabled", false);
pref("dom.serviceWorkers.openWindow.enabled", false);
// https://hg.mozilla.org/releases/mozilla-release/file/7eabe4d30cde/modules/libpref/init/all.js#l163
// https://hg.mozilla.org/releases/mozilla-release/file/7eabe4d30cde/dom/workers/ServiceWorkerManager.cpp#l2593
pref("dom.serviceWorkers.testUpdateOverOneDay", false);
pref("dom.webnotifications.serviceworker.enabled", false);

Отредактировано func4ptch4 (19-03-2019 14:26:17)

Отсутствует

 

№1315619-03-2019 17:49:53

leex
Участник
 
Группа: Members
Зарегистрирован: 24-03-2011
Сообщений: 244
UA: Firefox 50.0

Re: Custom Buttons

Большое спасибо! func4ptch4
В about:config все параметры с ServiceWorker выставил на false.
Просто и с ютубом  эти же проблемы с ошибкой содержимого
Даже кнопку сделал по аналогии с гмаил
Откуда вообще взялся у меня этот ServiceWorker..

Отредактировано leex (19-03-2019 17:52:41)

Отсутствует

 

№1315719-03-2019 22:09:06

Infocatcher
Not found
 
Группа: Extensions
Зарегистрирован: 24-05-2007
Сообщений: 4290
UA: Firefox 56.0

Re: Custom Buttons

Dumby пишет:

Если «Ошибка искажения содержимого» это лисья страница,
то можно попробовать как-то так

А если вот так?

Выделить код

Код:

    if(browser.currentURI.spec == "about:blank" || browser.webProgress.isLoadingDocument)
        setTimeout(wait, 25);
-   else {
+   else if(!browser.currentURI.spec.startsWith("about:neterror")) {

Итого

Выделить код

Код:

var tab = gBrowser.selectedTab = gBrowser.addTab("http://mail.google.com/mail/#i", {
    triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()
});
var browser = tab.linkedBrowser;
setTimeout(function wait() {
    if(browser.currentURI.spec == "about:blank" || browser.webProgress.isLoadingDocument)
        setTimeout(wait, 25);
    else if(!browser.currentURI.spec.startsWith("about:neterror")) {
        var wn = Components.interfaces.nsIWebNavigation;
        browser.reloadWithFlags(wn.LOAD_FLAGS_BYPASS_PROXY | wn.LOAD_FLAGS_BYPASS_CACHE);
    }
}, 0);


Во всяком случае, обычный обрыв соединения отлавливает (гуглопочта шалить отказывается, хотя вообще ошибку такую я встречал уже).


Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела

Отсутствует

 

№1315819-03-2019 23:30:41

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

Re: Custom Buttons

Infocatcher пишет:

ошибку такую я встречал

А я никогда не встречал, поэтому, сделав допущение,
что все страницы об ошибках примерно одинаковы,
экспериментировал со всегда доступной «Автономный режим».

Сейчас набрал bla.me, дождался этого «Firefox находится в автономном режиме»,
запускаю alert(gBrowser.selectedBrowser.currentURI.spec);
алертится http://bla.me/
Так что, возможно, не подходит.

Вобще, на ночнушке, правильно алертится и работает browser.documentURI.spec
Но, глядя на UA спрашивающего, пришлось проверить на соответствующей версии.
FF50 нет, но есть 48 и 52, так вот там, если спокойно сделать проверку,
тоже алертится правильно about:neterror?e=netOffline&u=http%3A//bla.me/&…

Но непосредственно в коде, browser.documentURI.spec там не работает,
пока не поднимешь таймаут до каких-то неприемлимых величин.
А frame script работает быстро и чётко.

Это всё я сейчас о многопроцессном режиме говорил.

Отсутствует

 

№1315920-03-2019 04:24:20

Stkvsky
Участник
 
Группа: Members
Зарегистрирован: 26-06-2012
Сообщений: 1209
UA: Firefox 42.0

Re: Custom Buttons

Может ли кто нибудь помочь переназначить кнопку автоматической прокрутки страницы со средней кнопки мышки на правую?

Отсутствует

 

№1316020-03-2019 18:09:30

Andrey_Krropotkin
Участник
 
Группа: Members
Зарегистрирован: 11-11-2011
Сообщений: 298
UA: Firefox 66.0

Re: Custom Buttons

Подскажите пожалуйста в 66 перестал работать из кода

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

Выделить код

Код:

((bar, button = true, insertAtTop = false, ctrlFcloseFinbar = false) => ({
    init(parent) {
        var has = bar = parent.querySelector("#appcontent > findbar");
        has || this.initFinbar(parent);
        var lo = bar.linkedObject;
        lo.listenCtrlF = ctrlFcloseFinbar
            ? listen => listen
                ? addEventListener("keydown", lo, true)
                : removeEventListener("keydown", lo, true)
            : () => {};
        has && !bar.hidden && lo.listenCtrlF(true);
        if (button) self._handleClick = () => bar.hidden
            ? bar.startFind(bar.FIND_NORMAL)
            : bar.collapsed || bar.close();
        addDestructor(lo.destroy, lo);
    },
    destroy(reason) {
        if (reason[5] != "e") return;
        bar.close();
        bar._browser = {};
        bar.remove();
        this.setProgressListener(false);
        for(var key of ["gFindBar", "gFindBarInitialized"])
            Object.defineProperty(window, key, this[key]);
        gBrowser[this.gBrKey] = this[this.gBrKey];
        Services.ppmm.removeDelayedProcessScript(this.url);
        Services.ppmm.loadProcessScript("data:," + encodeURIComponent(`
            Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_DEFAULT
            && Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_CONTENT
            || (nsvo => {
                var proto = nsvo.Finder.prototype;
                if ("_requestMatchesCount" in proto) {
                    proto.requestMatchesCount = proto._requestMatchesCount;
                    delete proto._requestMatchesCount;
                }
            })(Cu.import("resource://gre/modules/Finder.jsm", {}));`
        ) , false);
    },
    initFinbar(parent) {
        for(var tab of gBrowser.tabs) {
            if (!tab._findBar) continue;
            tab._findBar.browser = null;
            tab._findBar._browser = {};
            tab._findBar.remove();
            delete tab._findBar;
        }
        bar = document.createElement("findbar");
        var p = new Proxy({}, {get: () => () => {}});
        bar._browser = {finder: p, messageManager: p};
        parent.insertBefore(bar, insertAtTop ? parent.firstChild : null);
        bar.linkedObject = this;

        ["gFindBar", "gFindBarInitialized"].forEach((key, ind) => {
            this[key] = Object.getOwnPropertyDescriptor(window, key);
            delete window[key];
            window[key] = ind ? true : bar;
        });
                                
                                var ClearFindbarBtn = document.createElement("toolbarbutton");
                ClearFindbarBtn.setAttribute("id", "clearFindbar-button");
                ClearFindbarBtn.setAttribute("type", "button");
                ClearFindbarBtn.setAttribute("class", "toolbarbutton-1");
                //ClearFindbarBtn.setAttribute("oncommand", "if(gFindBar.getElement('findbar-textbox').value==''){gFindBar.close()}else{gFindBar.getElement('findbar-textbox').value='';gFindBar.onFindAgainCommand(false);}");
                
                ClearFindbarBtn.addEventListener("click", function(e) {
                                   if ( e.button == 0 ) {
                                       // поиск из буфера обмена
                                       e.preventDefault();
                                       var str = (gClipboard.read()).replace(/^\s+|\s+$/g,""); // убираем пробелы с концов текста
                                       gFindBar._findField.value = str;
                                       Highlight("hits", "greenLight");
                                      };
                                   if ( e.button == 2 )        
                                      if(gFindBar.getElement('findbar-textbox').value==''){gFindBar.close()}else{gFindBar.getElement('findbar-textbox').value='';gFindBar.onFindAgainCommand(false);} // очистить поле текстового ввода  
                                }, false);
                 
                /* ClearFindbarBtn.setAttribute("label", " Очистить "); */
                /* var doc = inspWin.document;*/
                
                                 
                var refNode = gFindBar.getElement("highlight");
                ClearFindbarBtn.setAttribute("tooltiptext", "ЛКМ - вставить из буфера. \nПКМ - очистить поиск");
                ClearFindbarBtn.setAttribute("style", "margin-right: 6px !important; margin-left: 6px !important;");
                ClearFindbarBtn.setAttribute("image", "data:image/x-icon;base64,AAABAAEADhAAAAEAIADoAwAAFgAAACgAAAAOAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5eXn/eXl5/3l5ef95eXn/eXl5/3l5ef95eXn/eXl5/ylTda0pU3X/KVN1/ylTdf8pU3X/HTpS/4WFhf/w8PL/8fHz//Hx8//x8fP/8fHz//Hx8/+FhYX/KVN1/yRJaP8jSGf/I0dl/yNHZP8YMEX/j4+P//Hx8//x8vP/8fLz//Hy8//x8vP/8fLz/4+Pj/8pU3X/JUxr/yVLav8kSmn/JElo/xkyR/+cnJz/8vLz//Ly9P/y8vT/8vL0//Ly9P/y8vT/nJyc/ylTdf8nTm3/Jk1t/yVMa/8lSmn/GjNJ/6urq//y8vT/8/P1//Pz9f/z8/X/8/P1//Pz9f+rq6v/KVN1/ydPb/8nTm7/Jk1t/yZMa/8aNEr/srKy//X19v/19vf/9fb3//X29//19vf/9fb3/7Kysv8pU3X/J1Bx/ydQb/8nTm//Jk1t/xs2S/+8vLz/+fr6//r7+//6+/v/ubm5/7e3t/+3t7f/ubm5/ylTdf8oUXP/KFBx/ydQcf8nT2//GzZN/76+vv/6+/v/+/v8//v7/P/ExMT/9vb2/7e3t/na2tpfKVN1/ylTdP8pUXP/KFBy/yhPcP8bN03/v7+///v7/P/7/Pz/+/z8/8rKyv+3t7f/4OLgaQAAAAApU3X/KVN1/yhSdP8oUnT/KFJy/xw4UP+/v7//v7+//7+/v/+/v7//uru7/2OBmf8AAAAAAAAAAClTdf8pU3X/KVN1/ylSdP8pUnT/JEpn/yRIZv8kSGX/I0dk/yNGY/8jRWL/KVN1/wAAAAAAAAAAKVN1/ylTdf8lS2n/IztO/yM7Tv8jO07/IztO/yM7Tv8jO07/JUtp/ydOb/8lS2n/AAAAAAAAAAApU3X/K2GQ/yhahv91dXX/XV1d/11dXf9dXV3/XV1d/4B/f/8oWob/Kmad/ylTdf8AAAAAAAAAAClTda0pU3X/KVN1/7O0tP/h4eD/3t7f/97f3//g4OD/s7S0/ylTdf8pU3X/KVN1rQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1yds1dXFv1XVxb9Wxxdc8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJUwFASZMCwAlTAsAI00LIys1CxcXFsEYFxbCJS01DAAlTQsAJk0LASZNCwAlTQUAAAAAAAAAAPwArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAASsQQAMrEEADKxBAAysQQAMrEEADKxB8PysQQAMrEE=");
                refNode.parentNode.insertBefore(ClearFindbarBtn,refNode);
                                
                var ClearFindbarBtn1 = document.createElement("toolbarbutton");
                ClearFindbarBtn1.setAttribute("id", "closeFindbar-button");
                ClearFindbarBtn1.setAttribute("class", "findbar-closebutton close-icon");
                ClearFindbarBtn1.setAttribute("tooltiptext", "Закрыть панель поиска");
                ClearFindbarBtn1.setAttribute("oncommand", "close();");
                var refNode1 = gFindBar.getElement("findbar-textbox");
                refNode1.parentNode.insertBefore(ClearFindbarBtn1,refNode1);
                var refNode2 = gFindBar.getElement("find-closebutton");
                refNode2.setAttribute("style", "display: none !important;"); 

// FindBar, поиск колесиком мыши ................................
        addEventListener('DOMMouseScroll', function(e) { gFindBar.onFindAgainCommand( e.detail < 0 ); updateHits("flash"); }, false, gFindBar );

        var key = "getCachedFindBar" in gBrowser ? "getCachedFindBar" : "getFindBar";
        this[this.gBrKey = key] = gBrowser[key];
        gBrowser[key] = () => bar;
        [
            "close", "startFind", "onMatchesCountResult",
            "_updateMatchesCount", "_onBrowserKeypress", "receiveMessage"

        ].forEach((key, ind) => {
            var func = bar[key].bind(bar);
            bar[key] = ind
                ? (...args) => this[key](...args) || func(...args)
                : (...args) => func(...args) || this[key](...args);
        });
        this.url = "data:," + encodeURIComponent(`
            Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_DEFAULT
            && Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_CONTENT
            || (nsvo => {
                var proto = nsvo.Finder.prototype;
                if ("_requestMatchesCount" in proto) return;
                proto._requestMatchesCount = proto.requestMatchesCount;
                proto.requestMatchesCount = ${
                    this.newRequestMatchesCount
                }
            })(Cu.import("resource://gre/modules/Finder.jsm", {}));`
        );
        delete this.newRequestMatchesCount;
        Services.ppmm.loadProcessScript(this.url, true);
    },
    newRequestMatchesCount: async function requestMatchesCount(aWord, aLinksOnly) {
        if (typeof aLinksOnly != "boolean") {

            var {linksOnly, data} = aLinksOnly;
            aLinksOnly = linksOnly;

            this.entireWord = data.entireWord;
            this.caseSensitive = data.caseSensitive;
            this.onModalHighlightChange(data.useModalHighlight);
            this.onHighlightAllChange(data.highlightAll);
            data.highlightAll && await this.highlighter.highlight(true, aWord, linksOnly);
            this._iterator && this._iterator.reset();
            var obj;
            Object.defineProperty(this, "_currentMatchesCountResult", {
                configurable: true, enumerable: true,
                get: (val = obj) => {
                    if (val) {
                        if (!val.total) val.total = new Number(0);
                        val.currentFound = val._currentFound;
                    }
                    return obj = val;
                },
                set: val => {
                    if (val) return obj = val;
                    delete this._currentMatchesCountResult;
                    return obj = this._currentMatchesCountResult = val;
                }
            });
            var lfr = this._lastFindResult;
            lfr !== null && lfr != Ci.nsITypeAheadFind.FIND_NOTFOUND
            || Object.defineProperty(this, "_lastFindResult", {
                configurable: true, enumerable: true, get: () => null,
                set: val => {
                    if (val == Ci.nsITypeAheadFind.FIND_WRAPPED)
                        val = Ci.nsITypeAheadFind.FIND_FOUND;
                    delete this._lastFindResult;
                    return this._lastFindResult = val;
                }
            });
        }
        this._requestMatchesCount(aWord, aLinksOnly);
    },
    close() {
        bar.collaped = false;
        this.setProgressListener(false);
        this.setBrowser(null, null);
    },
    startFind() {
        if (this.maybeCollapse(gBrowser.selectedBrowser))
            return true;
        if (bar.hidden)
            this.setBrowser(300),
            this.setProgressListener(true);
        else if (!ctrlFcloseFinbar)
            setTimeout(() => this.updateMatchesCount(), 100);
    },
    onMatchesCountResult(res) {
        if (!("currentFound" in res) || res.total == -1 || res.currentFound)
            return;

        bar._foundMatches.value = `${+res.total || "Нет"} совпадени${
            bar.pluralForm.get(res.total, "е;я;й")
        }.`;
        bar._foundMatches.hidden = false;
        return true;
    },
    _updateMatchesCount() {
        return true;
    },
    _onBrowserKeypress(e) {
        if (!bar.hidden) return;
        if (!e.charCode) return true;
        this.setBrowser(300);
        this.setProgressListener(true);
    },
    receiveMessage(msg) {
        msg.target = bar._browser;
    },

    progressListenerAdded: false,
    setProgressListener(add) {
        if (add) {
            if (this.progressListenerAdded) return;
            this.progressListenerAdded = true;
            gBrowser.addProgressListener(this);
            this.listenCtrlF(true);
        } else {
            if (!this.progressListenerAdded) return;
            this.progressListenerAdded = false;
            gBrowser.removeProgressListener(this);
            this.listenCtrlF(false);
        }
    },
    handleEvent(e) {
        if (
            e.ctrlKey && e.code == "KeyF"
            && !e.shiftKey && !e.altKey && !bar.collapsed
        )
            e.preventDefault(),
            e.stopPropagation(),
            bar.close();
        },
    updateMatchesCount() {
        var str = bar._findField.value;
        if (!str) return;
        var data = {
            entireWord: bar._entireWord,
            caseSensitive: bar._typeAheadCaseSensitive,
            highlightAll: bar._highlightAll,
            useModalHighlight: bar._useModalHighlight
        };
        bar.browser.finder.requestMatchesCount(
            bar._findField.value, 
            {linksOnly: bar._findMode == bar.FIND_LINKS, data}
                );
    },
    maybeCollapse(br) {
        return br.isSyntheticDocument ||
            br.documentContentType == "application/vnd.mozilla.xul+xml";
    },
    setBrowser(updateDelay, br = gBrowser.selectedBrowser) {
        if (bar._browser != br) {
            var b = bar._browser;
            if (b) {
                b.messageManager.removeMessageListener("Findbar:Mouseup", bar);
                b.finder.removeResultListener(bar);
                bar._highlightAll && b.finder.highlight(false);
            }
            if (br) {
                br.messageManager.addMessageListener("Findbar:Mouseup", bar);
                bar._updateBrowserWithState();
            }
            bar._browser = br;
        }
        if (!br) return;
        bar._updateStatusUI();
        bar._foundMatches.value = "";
        br.finder.addResultListener(bar);
        if (
            !(bar.collapsed = this.maybeCollapse(br))
            && br.currentURI.spec != "about:blank"
            && updateDelay !== null
        )
            updateDelay
                ? setTimeout(this.updateMatchesCount, updateDelay)
                : this.updateMatchesCount();
    },
    onStateChange(wpr, req, state) {
        state & Ci.nsIWebProgressListener.STATE_STOP && this.setBrowser();
        },
    onLocationChange(wpr, req) {
        req || Components.stack.formattedStack.includes("SessionStore.jsm")
        || this.setBrowser();
    }
   
   
}).init(document.getElementById("appcontent")))();


1. var refNode = gFindBar.getElement("highlight"); в консоли пишит gFindBar is undefined
2. В этом коде в консоли пишит openInTabs is undefined ссылается на строчку
eval("PlacesUIUtils.openContainerNodeInTabs = " + openInTabs.toString().replace(' {', '{\n openTabWithoutLoading(aNode);\n if (aNode.itemId !== -1) return;\n'));
скрытый текст

Выделить код

Код:

// Открыть всё из папки закладок в новых вкладках не загружая страниц
(function () {
      var ss = "nsISessionStore" in Components.interfaces
                            ? (
                                Components.classes["@mozilla.org/browser/sessionstore;1"]
                                || Components.classes["@mozilla.org/suite/sessionstore;1"]
                            ).getService(Components.interfaces.nsISessionStore)
                            : SessionStore;
   // изменить внутреннюю функцию Firefox которая открывает всё во вкладках  
   const openInTabs = PlacesUIUtils.openContainerNodeInTabs;
   eval("PlacesUIUtils.openContainerNodeInTabs = " + openInTabs.toString().replace(' {', '{\n openTabWithoutLoading(aNode);\n if (aNode.itemId !== -1) return;\n'));
   addDestructor(function() {PlacesUIUtils.openContainerNodeInTabs = openInTabs} );
   
   // открыть всё из папки закладок
   function openTabWithoutLoading( aNode ) {
      aNode.containerOpen = true;
      
      for ( var i = 0; i < aNode.childCount; ++i ) {
            var item = aNode.getChild(i);
            if ( !PlacesUtils.nodeIsURI( item ) ) continue;
            
            // добавить вкладку с указанными данными не загружая страницы
            var tab = gBrowser.addTab(null, {
    triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()
});            
            ss.setTabState( tab, JSON.stringify({
               entries: [ { url: item.uri, title: item.title } ],
               lastAccessed: 0,
               index: 1,
               hidden: false,
               attributes: {},
               image: item.icon.replace("moz-anno:favicon:", "")
            }));    
            }
                        
      // если текущая пустая вкладка закрыть и переключится на соседнюю вкладку 
      var blank = isBlankPageURL(content.location.href);
      if ( !blank ) return;
      gBrowser.removeCurrentTab();
      gBrowser.mTabContainer.advanceSelectedTab(1);         
   };    
})();


Infocatcher установил с вашей страницы Source Editor version 0.1.0a9 - 2019-03-01. В поле редактора в контекстном меню видать пункт только перейти к строке, а остальные пункты не видать - все белые.

Отредактировано Andrey_Krropotkin (23-03-2019 22:06:15)

Отсутствует

 

№1316120-03-2019 20:11:58

Infocatcher
Not found
 
Группа: Extensions
Зарегистрирован: 24-05-2007
Сообщений: 4290
UA: Firefox 56.0

Re: Custom Buttons

Andrey_Krropotkin пишет:

Infocatcher установил с вашей страницы Source Editor version 0.1.0a9 - 2019-03-01. В поле редактора в контекстном меню видать пункт только перейти к строке, а остальные пункты не видать - все белые.

Это на Firefox 66?
chrome://global/content/editMenuOverlay.xul с локализацией и стандартными командами утопили... А API для встраивания редактора, надо думать, так и не завезли.
Зато завезли какие-то хипстерские выкрутасы:

Выделить код

Код:

win.MozXULElement.insertFTLIfNeeded("toolkit/main-window/editmenu.ftl");

Только у меня от

Выделить код

Код:

const MenuItem = require("devtools/client/framework/menu-item");

и прочих присоседенных инкапсуляций смузи потёк.
Пока что вкрутил только часть надписей: https://github.com/Infocatcher/Custom_B … aac0520b41
Но команды, видимо, придется добавлять вручную...


Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела

Отсутствует

 

№1316220-03-2019 21:23:56

Andrey_Krropotkin
Участник
 
Группа: Members
Зарегистрирован: 11-11-2011
Сообщений: 298
UA: Firefox 66.0

Re: Custom Buttons

Infocatcher На 66 появилось контекстное меню, кроме 2-х предпоследних пунктов. Но оно неактивно. Т.е. отменить, вырезать , копировать, вставить, удалить, выделить все  не работает.
Да еще вопрос можно ли добавить, где нибудь в опциях выбор размера шрифта, а то в редакторе для меня строчки слишком маленькие.
Да было бы вообще классно, если ваши наработки  Source Editor, Toggle on Top button for Custom Buttons и Edit Custom Button in Tab внедрить совместно с Dumby в сам адон Custom Buttons.
Хотя мечтать не вредно.

Отредактировано Andrey_Krropotkin (20-03-2019 21:46:02)

Отсутствует

 

№1316320-03-2019 23:49:32

Infocatcher
Not found
 
Группа: Extensions
Зарегистрирован: 24-05-2007
Сообщений: 4290
UA: Firefox 56.0

Re: Custom Buttons

Andrey_Krropotkin пишет:

На 66 появилось контекстное меню, кроме 2-х предпоследних пунктов. Но оно неактивно. Т.е. отменить, вырезать , копировать, вставить, удалить, выделить все  не работает.

Я пишет:

Но команды, видимо, придется добавлять вручную...

Код для обработки нажатий на пункты меню, похоже, надо теперь реализовывать вручную. Надо подумать еще. Так что пока только надписи, теперь для всех пунктов:
https://github.com/Infocatcher/Custom_B … rce_Editor

Andrey_Krropotkin пишет:

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

Я ожидал, что применятся настройки Scratchpad'а (а для шрифта, как оказалось, есть: devtools.scratchpad.editorFontSize), но, видимо, удобные в применении модули утонули вместе с нормальными расширениями.
Настройку добавил, но не знаю, в каких версиях будет работать. В свежей Nightly заработало.


Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела

Отсутствует

 

№1316421-03-2019 12:22:03

drage2
Забанен
 
Группа: Members
Откуда: Донецк
Зарегистрирован: 23-11-2017
Сообщений: 392
UA: Firefox 66.0

Re: Custom Buttons

Не первый человек жалуется на контекст...А, у меня работает и в 66 и в 67(W-7 - без аэро)
https://s17.directupload.net/images/190321/temp/tkbfuuk2.png

Отсутствует

 

№1316522-03-2019 21:10:13

vurdalak
Участник
 
Группа: Members
Зарегистрирован: 03-06-2005
Сообщений: 173
UA: Firefox 66.0

Re: Custom Buttons

Так на каких браузерах вообще сейчас custom button работают и где скачать последнюю версию?

Объясните по человечески как ставить CB на новый браузер (обычный FF). Хоть бы шапку в ветке сделали что ли за 10 лет то, или сидеть по полдня пол форума листать , чтобы догнать что к чему (времени просто вагон наврное у всех) ... на гитхабе в инфокетчера ни фига нет, нигде ничего нет, ни манула ни ............. !
Это что какая то нелегальная полуофициальная ветка форума, что все так скрыто или что?

Отредактировано vurdalak (22-03-2019 21:41:58)

Отсутствует

 

№1316622-03-2019 21:35:53

Andrey_Krropotkin
Участник
 
Группа: Members
Зарегистрирован: 11-11-2011
Сообщений: 298
UA: unknown 0.0

Re: Custom Buttons

vurdalak посмотри предыдущею страницу. Пост Dumby. Рассчитана как для для 66 так и выше.

Отсутствует

 

№1316722-03-2019 21:43:25

vurdalak
Участник
 
Группа: Members
Зарегистрирован: 03-06-2005
Сообщений: 173
UA: Firefox 66.0

Re: Custom Buttons

Andrey_Krropotkin пишет:

vurdalak посмотри предыдущею страницу. Пост Dumby. Рассчитана как для для 66 так и выше.

Да читал я , и что ?
Где этот config.js находится. Для какого браузера предназначен?
Какое расширение их этих двух ставить?
Как ставить, как дебаг или просто?
Подписывать или нет?
Миллион вопросов

Отсутствует

 

№1316822-03-2019 22:44:39

okkamas_knife
We are the Borg.       Resistance is futile.
 
Группа: Members
Зарегистрирован: 21-10-2009
Сообщений: 9520
UA: Seamonkey 2.14

Re: Custom Buttons

vurdalak пишет: Объясните по человечески как ставить CB на новый браузер (обычный FF). Хоть бы шапку в ветке сделали что ли за 10 лет то, или сидеть по полдня пол форума листать , чтобы догнать что к чему (времени просто вагон наврное у всех) ... на гитхабе в инфокетчера ни фига нет, нигде ничего нет, ни манула ни ............. !
Это что какая то нелегальная полуофициальная ветка форума, что все так скрыто или что?

Официально СВ давно помер благодаря стараниям мозилловцев, то что сейчас есть это клоны-зомби изображающие активность с помощью кучи костылей и местных некромантов-обновленцев у которых куча времени на то чтоб ковыряться в коде с каждым выходом очередной версии фф и пристраивать костыли вместо того чтоб просто пользоваться старой версией.
так что выбирай использовать последнюю официальную версию СВ на соответствующей версии фф
Version 0.0.5.8.9 Released March 20, 2016 120.5 KiB Works with Firefox 1.5 - 56.*
либо копаться с кодом и мучать некромантов вопросами.


я помню те времена когда обновления программ убирали проблемы и исправляли баги, а не добавляли их.

Отсутствует

 

№1316922-03-2019 22:57:36

vurdalak
Участник
 
Группа: Members
Зарегистрирован: 03-06-2005
Сообщений: 173
UA: Firefox 66.0

Re: Custom Buttons

okkamas_knife пишет:

я помню те времена когда обновления программ убирали проблемы и исправляли баги, а не добавляли их.

Золотые слова! :beer:

p.s. Сам то на SeaMonkey сидишь...

Отредактировано vurdalak (22-03-2019 22:58:35)

Отсутствует

 

№1317022-03-2019 23:32:47

drage2
Забанен
 
Группа: Members
Откуда: Донецк
Зарегистрирован: 23-11-2017
Сообщений: 392
UA: Firefox 66.0

Re: Custom Buttons

СВ с костылем только в 67, в 66 можно и без, так малость рихтануть omni.ja///
Правда, 67 бэты  это нечто, блуждающий профайл один чего стоит...Мазиловцам делать нечего, только и успевают "поганки заворачивать"...

Отсутствует

 

№1317123-03-2019 14:46:03

Esper
Участник
 
Группа: Members
Зарегистрирован: 07-08-2016
Сообщений: 11
UA: Firefox 65.0

Re: Custom Buttons

А) Подскажите, пожалуйста, актуальный код для js-конфига, который включает поддержку старых расширений и отключает проверку подписей для версий: ESR 60, RELEASE 66.
По теме пробежался, код из некоторых постов вроде работает, даже скрипты в закрепленном посте по-моему включают легаси. Но код везде немного отличается - не понятно, что выбирать.

Б) Понимаю, что тема про CB, но только тут запускают старые расширения. Есть ли возможность таким же образом оживить другие крупные дополнения: Session Manager, Fire Gestures, Tab Utilities и т.д.?

Пробовал их запускать, получаю различные ошибки:

скрытый текст
У Session Manager:
Error loading bootstrap.js for {1280606b-2510-4fe0-97ef-9b5a22eafe30}: SyntaxError: missing { before function body (resource://gre/modules/addons/XPIProvider.jsm -> jar:file:///extensions/%7B1280606b-2510-4fe0-97ef-9b5a22eafe30%7D.xpi!/bootstrap.js:35:18) JS Stack trace: loadBootstrapScope@XPIProvider.jsm:4299:9
callBootstrapMethod@XPIProvider.jsm:4363:9
startup@XPIProvider.jsm:2253:13
callProvider@AddonManager.jsm:253:12
_startProvider@AddonManager.jsm:728:5
startup@AddonManager.jsm:892:9
startup@AddonManager.jsm:2976:5
observe@addonManager.js:63:9

У Tab Utilities:
SyntaxError: missing { before function body  browser.js:537:41
SyntaxError: yield expression is only valid in generators  tabutils.js:785:60
и т.д.

Отсутствует

 

№1317223-03-2019 20:56:59

Andrey_Krropotkin
Участник
 
Группа: Members
Зарегистрирован: 11-11-2011
Сообщений: 298
UA: Firefox 66.0

Re: Custom Buttons

vurdalak почитайте:
1. Как отключить проверку цифровых подписей в дополнениях Firefox, где расписано про config-prefs.js и config.js и куда их кидать.
config.js в папку установки Firefox: C:\Program Files\Mozilla Firefox
config-prefs.js в папку: C:\Program Files\Mozilla Firefox\defaults\pref ( остается прежним - не меняем).
2. После этого смотрим пост Dumby, где 1 пунктом идет содержимое config.js и сам аддон.
3. В посте  есть пункт 2 про bootstrap-loader.js для этого надо еще посмотреть его прежний пост и дальше разъяснения после этого поста
4. Если непонятно про 2 пункт вопросы задавать Dumby

Я пока пользуюсь 1 пунктом, но есть кто и вторым. Есть пока минусы у дополнения - оно сыровато для х64(многопроцессорного) Firefox, но благодаря Dumby, как говорит okkamas_knife - местных некромантов-обновленцев у которых куча времени на то чтоб ковыряться в коде, это дополнение до сих пор работает. И неизвестно есть у него время или нет, мы засчет него тут на форуме существуем.

Отредактировано Andrey_Krropotkin (23-03-2019 22:44:14)

Отсутствует

 

№1317323-03-2019 21:08:52

Garalf
Участник
 
Группа: Members
Зарегистрирован: 19-09-2017
Сообщений: 166
UA: Firefox 66.0

Re: Custom Buttons

Andrey_Krropotkin
Спасибо, что напомнил.

Огромная благодарность Dumby и Infocatcher за работающее CB

Отсутствует

 

№1317424-03-2019 11:47:15

drage2
Забанен
 
Группа: Members
Откуда: Донецк
Зарегистрирован: 23-11-2017
Сообщений: 392
UA: Firefox 66.0

Re: Custom Buttons

Вот это движуха пошла, прям борьба нанайских мальчиков. а креатив то где? Последний bootstrap-loader.js от Dumby + СВ (03 ) решает все проблемы . Пользоваться, конечно, надо уметь. В65-66 можно и без этого обойтись...Но в 67  уже никак, только с bootstrap-loader.js. Дальше каждый сам  мозгами вертеть должен. К, примеру, в папке defaults-pref- файл -не config.js , а, all-settings.js

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

Выделить код

Код:

pref("general.config.obscure_value", 0);
pref("general.config.filename", "bootstrap-loader.js");


В каталоге - просто bootstrap-loader.js , причем совмещен с префами mozilla.cfg
скрытый текст

Выделить код

Код:

//
try {
    Cu.createDocumentEncoder && Cc["@mozilla.org/moz/jssubscript-loader;1"]
        .getService(Ci.mozIJSSubScriptLoader).loadSubScript(String.raw`
            data:,var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");%0Avar {AddonManager} = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");%0A%0Athis.lazyModules = {%0A%09OS: "resource://gre/modules/osfile.jsm",%0A%09Services: "resource://gre/modules/Services.jsm",%0A%09ConsoleAPI: "resource://gre/modules/Console.jsm",%0A%09Blocklist: "resource://gre/modules/Blocklist.jsm",%0A%09AddonInternal: "resource://gre/modules/addons/XPIDatabase.jsm"%0A};%0Aif ("@mozilla.org/intl/domlocalization;1" in Cc)%0A%09this.lazyModules.RDFDataSource = "resource://gre/modules/addons/RDFDataSource.jsm";%0Aelse%0A%09// Firefox 67+%0A%09// Bug 1523194 - Remove XPIDL for DOMLocalization and use do_ImportModule instead%0A%09// https://bugzilla.mozilla.org/show_bug.cgi?id=1523194%0A%09//%0A%09// Bug 857458 - Remove support for update.rdf%0A%09// https://bugzilla.mozilla.org/show_bug.cgi?id=857458%0A%0A%09XPCOMUtils.defineLazyGetter(this, "RDFDataSource", () => {%0A%09%09var obs = {};%0A%09%09var scs = Cc["@mozilla.org/streamConverters;1"].getService(Ci.nsIStreamConverterService);%0A%09%09var sis = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);%0A%09%09var sl =  Cc["@mozilla.org/network/stream-loader;1"].createInstance(Ci.nsIStreamLoader);%0A%0A%09%09var gzip = "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";%0A%09%09sis.data = atob(gzip);%0A%09%09obs.onStreamComplete = (a, b, c, d, result) => Cu.evalInSandbox(String.fromCharCode(...result), this);%0A%09%09sl.init(obs);%0A%09%09var converter = scs.asyncConvertData("gzip", "uncompressed", sl, null);%0A%09%09converter.onStartRequest(null, null);%0A%0A%09%09var args = [null, null, sis, 0, sis.data.length];%0A%09%09// Bug 1525319 - Investigate if we can remove Context argument from Channel methods (Firefox 67+)%0A%09%09// https://bugzilla.mozilla.org/show_bug.cgi?id=1525319%0A%09%09if (converter.onDataAvailable.length == 4) args.shift();%0A%09%09converter.onDataAvailable(...args);%0A%0A%09%09converter.onStopRequest(null, null, null);%0A%0A%09%09return RDFDataSource;%0A%09});%0AXPCOMUtils.defineLazyModuleGetters(this, this.lazyModules);%0Adelete this.lazyModules;%0A%0AXPCOMUtils.defineLazyGetter(this, "BOOTSTRAP_REASONS", () =>%0A%09ChromeUtils.import("resource://gre/modules/addons/XPIProvider.jsm", {})%0A%09%09.XPIProvider.BOOTSTRAP_REASONS%0A);%0AXPCOMUtils.defineLazyGetter(this, "logger", () =>%0A%09ChromeUtils.import("resource://gre/modules/Log.jsm", {})%0A%09%09.Log.repository.getLogger("addons.bootstrap")%0A);%0A%0A%0A// RDFManifestConverter.jsm%0Aconst RDFURI_INSTALL_MANIFEST_ROOT = "urn:mozilla:install-manifest";%0A%0Afunction EM_R(aProperty) {%0A%09return %60http://www.mozilla.org/2004/em-rdf%23%24{aProperty}%60;%0A}%0Afunction getValue(literal) {%0A%09return literal && literal.getValue();%0A}%0Afunction getProperty(resource, property) {%0A%09return getValue(resource.getProperty(EM_R(property)));%0A}%0A%0Aclass Manifest {%0A%09constructor(ds) {%0A%09%09this.ds = ds;%0A%09}%0A%09static loadFromString(text) {%0A%09%09return new this(RDFDataSource.loadFromString(text));%0A%09}%0A%09static loadFromBuffer(buffer) {%0A%09%09return new this(RDFDataSource.loadFromBuffer(buffer));%0A%09}%0A%09static async loadFromFile(uri) {%0A%09%09return new this(await RDFDataSource.loadFromFile(uri));%0A%09}%0A}%0A%0Aclass InstallRDF extends Manifest {%0A%09_readProps(source, obj, props) {%0A%09%09for (let prop of props) {%0A%09%09%09let val = getProperty(source, prop);%0A%09%09%09if (val != null) {%0A%09%09%09%09obj[prop] = val;%0A%09%09%09}%0A%09%09}%0A%09}%0A%09_readArrayProp(source, obj, prop, target, decode = getValue) {%0A%09%09let result = Array.from(%0A%09%09%09source.getObjects(EM_R(prop)), target => decode(target)%0A%09%09);%0A%09%09if (result.length) {%0A%09%09%09obj[target] = result;%0A%09%09}%0A%09}%0A%09_readArrayProps(source, obj, props, decode = getValue) {%0A%09%09for (let [prop, target] of Object.entries(props)) {%0A%09%09%09this._readArrayProp(source, obj, prop, target, decode);%0A%09%09}%0A%09}%0A%09_readLocaleStrings(source, obj) {%0A%09%09this._readProps(source, obj, ["name", "description", "creator", "homepageURL"]);%0A%09%09this._readArrayProps(source, obj, {%0A%09%09%09locale: "locales",%0A%09%09%09developer: "developers",%0A%09%09%09translator: "translators",%0A%09%09%09contributor: "contributors",%0A%09%09});%0A%09}%0A%09decode() {%0A%09%09let root = this.ds.getResource(RDFURI_INSTALL_MANIFEST_ROOT);%0A%09%09let result = {};%0A%0A%09%09let props = [%0A%09%09%09"id", "version", "type", "updateURL", "optionsURL",%0A%09%09%09"optionsType", "aboutURL", "iconURL",%0A%09%09%09"bootstrap", "unpack", "strictCompatibility"%0A%09%09];%0A%09%09this._readProps(root, result, props);%0A%0A%09%09let decodeTargetApplication = source => {%0A%09%09%09let app = {maxVersion: "*"};%0A%09%09%09this._readProps(source, app, ["id", "minVersion"]);%0A%09%09%09return app;%0A%09%09};%0A%0A%09%09let decodeLocale = source => {%0A%09%09%09let localized = {};%0A%09%09%09this._readLocaleStrings(source, localized);%0A%09%09%09return localized;%0A%09%09};%0A%0A%09%09this._readLocaleStrings(root, result);%0A%0A%09%09this._readArrayProps(%0A%09%09%09root, result, {"targetPlatform": "targetPlatforms"}%0A%09%09);%0A%09%09this._readArrayProps(%0A%09%09%09root, result, {"targetApplication": "targetApplications"}, decodeTargetApplication%0A%09%09);%0A%09%09this._readArrayProps(%0A%09%09%09root, result, {"localized": "localized"}, decodeLocale%0A%09%09);%0A%09%09this._readArrayProps(%0A%09%09%09root, result, {"dependency": "dependencies"}, source => getProperty(source, "id")%0A%09%09);%0A%09%09return result;%0A%09}%0A}%0A// fim RDFManifestConverter.jsm%0A%0A%0A// BootstrapLoader.jsm%0A/**%0A * Valid IDs fit this pattern.%0A */%0Avar gIDTest = /^(\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}|[a-z0-9-\._]*\@[a-z0-9-\._]+)$/i;%0A%0A// Properties that exist in the install manifest%0Aconst PROP_METADATA%09= [%0A%09"id", "version", "type", "internalName", "updateURL",%0A%09"optionsURL", "optionsType", "aboutURL", "iconURL"%0A];%0Aconst PROP_LOCALE_SINGLE = ["name", "description", "creator", "homepageURL"];%0Aconst PROP_LOCALE_MULTI%09= ["developers", "translators", "contributors"];%0A%0A// Map new string type identifiers to old style nsIUpdateItem types.%0A// Retired values:%0A// 32 = multipackage xpi file%0A// 8 = locale%0A// 256 = apiextension%0A// 128 = experiment%0A// theme = 4%0Aconst TYPES = {%0A%09extension: 2,%0A%09dictionary: 64,%0A};%0A%0Aconst COMPATIBLE_BY_DEFAULT_TYPES = {%0A%09extension: true,%0A%09dictionary: true,%0A};%0A%0Aconst hasOwnProperty = Function.call.bind(Object.prototype.hasOwnProperty);%0A%0Afunction isXPI(filename) {%0A%09let ext = filename.slice(-4).toLowerCase();%0A%09return ext === ".xpi" || ext === ".zip";%0A}%0A%0A/**%0A * Gets an nsIURI for a file within another file, either a directory or an XPI%0A * file. If aFile is a directory then this will return a file: URI, if it is an%0A * XPI file then it will return a jar: URI.%0A *%0A * @param {nsIFile} aFile%0A *%09%09The file containing the resources, must be either a directory or an XPI file%0A *%0A * @param {string} aPath%0A *%09%09The path to find the resource at, "/" separated. If aPath is empty%0A *%09%09then the uri to the root of the contained files will be returned%0A *%0A * @returns {nsIURI}%0A *%09%09An nsIURI pointing at the resource%0A */%0Afunction getURIForResourceInFile(aFile, aPath) {%0A%09if (!isXPI(aFile.leafName)) {%0A%09%09let resource = aFile.clone();%0A%09%09if (aPath)%0A%09%09%09aPath.split("/").forEach(part => resource.append(part));%0A%0A%09%09return Services.io.newFileURI(resource);%0A%09}%0A%09return buildJarURI(aFile, aPath);%0A}%0A%0A/**%0A * Creates a jar: URI for a file inside a ZIP file.%0A *%0A * @param {nsIFile} aJarfile%0A *%09%09The ZIP file as an nsIFile%0A *%0A * @param {string} aPath%0A *%09%09The path inside the ZIP file%0A *%0A * @returns {nsIURI}%0A *%09%09An nsIURI for the file%0A */%0Afunction buildJarURI(aJarfile, aPath) {%0A%09let uri = Services.io.newFileURI(aJarfile);%0A%09uri = "jar:" + uri.spec + "!/" + aPath;%0A%09return Services.io.newURI(uri);%0A}%0A%0Avar BootstrapLoader = {%0A%09name: "bootstrap",%0A%09manifestFile: "install.rdf",%0A%09async loadManifest(pkg) {%0A%09%09/**%0A%09%09 * Reads locale properties from either the main install manifest root%0A%09%09 * or an em:localized section in the install manifest.%0A%09%09 *%0A%09%09 * @param {Object} aSource%0A%09%09 *%09%09The resource to read the properties from.%0A%09%09 *%0A%09%09 * @param {boolean} isDefault%0A%09%09 *%09%09True if the locale is to be read from the main install manifest root%0A%09%09 *%0A%09%09 * @param {string[]} aSeenLocales%0A%09%09 *%09%09An array of locale names already seen for this install manifest.%0A%09%09 *%09%09Any locale names seen as a part of this function will be added to this array%0A%09%09 *%0A%09%09 * @returns {Object}%0A%09%09 *%09%09An object containing the locale properties%0A%09%09 */%0A%09%09function readLocale(aSource, isDefault, aSeenLocales) {%0A%09%09%09let locale = {};%0A%09%09%09if (!isDefault) {%0A%09%09%09%09locale.locales = [];%0A%09%09%09%09for (let localeName of aSource.locales || []) {%0A%09%09%09%09%09if (!localeName) {%0A%09%09%09%09%09%09logger.warn("Ignoring empty locale in localized properties");%0A%09%09%09%09%09%09continue;%0A%09%09%09%09%09}%0A%09%09%09%09%09if (aSeenLocales.includes(localeName)) {%0A%09%09%09%09%09%09logger.warn("Ignoring duplicate locale in localized properties");%0A%09%09%09%09%09%09continue;%0A%09%09%09%09%09}%0A%09%09%09%09%09aSeenLocales.push(localeName);%0A%09%09%09%09%09locale.locales.push(localeName);%0A%09%09%09%09}%0A%0A%09%09%09%09if (locale.locales.length == 0) {%0A%09%09%09%09%09logger.warn("Ignoring localized properties with no listed locales");%0A%09%09%09%09%09return null;%0A%09%09%09%09}%0A%09%09%09}%0A%09%09%09for (let prop of [...PROP_LOCALE_SINGLE, ...PROP_LOCALE_MULTI]) {%0A%09%09%09%09if (hasOwnProperty(aSource, prop)) {%0A%09%09%09%09%09locale[prop] = aSource[prop];%0A%09%09%09%09}%0A%09%09%09}%0A%09%09%09return locale;%0A%09%09}%0A%0A%09%09let manifestData = await pkg.readString("install.rdf");%0A%09%09let manifest = InstallRDF.loadFromString(manifestData).decode();%0A%0A%09%09let addon = new AddonInternal();%0A%09%09for (let prop of PROP_METADATA) {%0A%09%09%09if (hasOwnProperty(manifest, prop)) {%0A%09%09%09%09addon[prop] = manifest[prop];%0A%09%09%09}%0A%09%09}%0A%09%09if (!addon.type) {%0A%09%09%09addon.type = "extension";%0A%09%09} else {%0A%09%09%09let type = addon.type;%0A%09%09%09addon.type = null;%0A%09%09%09for (let name in TYPES) {%0A%09%09%09%09if (TYPES[name] == type) {%0A%09%09%09%09%09addon.type = name;%0A%09%09%09%09%09break;%0A%09%09%09%09}%0A%09%09%09}%0A%09%09}%0A%09%09if (!(addon.type in TYPES))%0A%09%09%09throw new Error("Install manifest specifies unknown type: " + addon.type);%0A%0A%09%09if (!addon.id)%0A%09%09%09throw new Error("No ID in install manifest");%0A%09%09if (!gIDTest.test(addon.id))%0A%09%09%09throw new Error("Illegal add-on ID " + addon.id);%0A%09%09if (!addon.version)%0A%09%09%09throw new Error("No version in install manifest");%0A%0A%09%09addon.strictCompatibility =%0A%09%09%09!(addon.type in COMPATIBLE_BY_DEFAULT_TYPES) ||%0A%09%09%09"strictCompatibility" in manifest && manifest.strictCompatibility == "true";%0A%0A%09%09// Only read these properties for extensions.%0A%09%09if (addon.type == "extension") {%0A%09%09%09if (manifest.bootstrap != "true") {%0A%09%09%09%09throw new Error("Non-restartless extensions no longer supported");%0A%09%09%09}%0A%09%09%09if (%0A%09%09%09%09addon.optionsType &&%0A%09%09%09%09addon.optionsType != AddonManager.OPTIONS_TYPE_INLINE_BROWSER &&%0A%09%09%09%09addon.optionsType != AddonManager.OPTIONS_TYPE_TAB%0A%09%09%09) {%0A%09%09%09%09throw new Error("Install manifest specifies unknown optionsType: " + addon.optionsType);%0A%09%09%09}%0A%09%09} else {%0A%09%09%09// Convert legacy dictionaries into a format the WebExtension%0A%09%09%09// dictionary loader can process.%0A%09%09%09if (addon.type === "dictionary") {%0A%09%09%09%09addon.loader = null;%0A%09%09%09%09let dictionaries = {};%0A%09%09%09%09await pkg.iterFiles(({path}) => {%0A%09%09%09%09%09let match = /^dictionaries\/([^\/]+)\.dic$/.exec(path);%0A%09%09%09%09%09if (match) {%0A%09%09%09%09%09%09let lang = match[1].replace(/_/g, "-");%0A%09%09%09%09%09%09dictionaries[lang] = match[0];%0A%09%09%09%09%09}%0A%09%09%09%09});%0A%09%09%09%09addon.startupData = {dictionaries};%0A%09%09%09}%0A%0A%09%09%09// Only extensions are allowed to provide an optionsURL, optionsType,%0A%09%09%09// optionsBrowserStyle, or aboutURL. For all other types they are silently ignored%0A%09%09%09addon.aboutURL = null;%0A%09%09%09addon.optionsBrowserStyle = null;%0A%09%09%09addon.optionsType = null;%0A%09%09%09addon.optionsURL = null;%0A%09%09}%0A%0A%09%09addon.defaultLocale = readLocale(manifest, true);%0A%09%09let defaultLocaleEntries = Object.entries(addon.defaultLocale);%0A%0A%09%09let seenLocales = [];%0A%09%09addon.locales = [];%0A%09%09for (let localeData of manifest.localized || []) {%0A%09%09%09let locale = readLocale(localeData, false, seenLocales);%0A%09%09%09if (locale) {%0A%09%09%09%09for(let [key, val] of defaultLocaleEntries)%0A%09%09%09%09%09key in locale || Reflect.set(locale, key, val);%0A%09%09%09%09addon.locales.push(locale);%0A%09%09%09}%0A%09%09}%0A%0A%09%09addon.dependencies = Object.freeze(%0A%09%09%09"dependencies" in manifest ? Array.from(new Set(manifest.dependencies)) : []%0A%09%09);%0A%0A%09%09let seenApplications = [];%0A%09%09addon.targetApplications = [];%0A%09%09for (let targetApp of manifest.targetApplications || []) {%0A%09%09%09if (!targetApp.id || !targetApp.minVersion || !targetApp.maxVersion) {%0A%09%09%09%09logger.warn("Ignoring invalid targetApplication entry in install manifest");%0A%09%09%09%09continue;%0A%09%09%09}%0A%09%09%09if (seenApplications.includes(targetApp.id)) {%0A%09%09%09%09logger.warn(%0A%09%09%09%09%09"Ignoring duplicate targetApplication entry for " + targetApp.id + " in install manifest"%0A%09%09%09%09);%0A%09%09%09%09continue;%0A%09%09%09}%0A%09%09%09seenApplications.push(targetApp.id);%0A%09%09%09addon.targetApplications.push(targetApp);%0A%09%09}%0A%0A%09%09// Note that we don't need to check for duplicate targetPlatform entries since%0A%09%09// the RDF service coalesces them for us.%0A%09%09addon.targetPlatforms = [];%0A%09%09for (let targetPlatform of manifest.targetPlatforms || []) {%0A%09%09%09let platform = {%0A%09%09%09%09os: null,%0A%09%09%09%09abi: null,%0A%09%09%09};%0A%0A%09%09%09let pos = targetPlatform.indexOf("_");%0A%09%09%09if (pos != -1) {%0A%09%09%09%09platform.os = targetPlatform.substring(0, pos);%0A%09%09%09%09platform.abi = targetPlatform.substring(pos + 1);%0A%09%09%09} else {%0A%09%09%09%09platform.os = targetPlatform;%0A%09%09%09}%0A%09%09%09addon.targetPlatforms.push(platform);%0A%09%09}%0A%0A%09%09addon.userDisabled = false;%0A%09%09addon.softDisabled = addon.blocklistState == Blocklist.STATE_SOFTBLOCKED;%0A%09%09addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT;%0A%0A%09%09addon.userPermissions = null;%0A%0A%09%09addon.icons = {};%0A%09%09if (await pkg.hasResource("icon.png")) {%0A%09%09%09addon.icons[32] = "icon.png";%0A%09%09%09addon.icons[48] = "icon.png";%0A%09%09}%0A%0A%09%09if (await pkg.hasResource("icon64.png")) {%0A%09%09%09addon.icons[64] = "icon64.png";%0A%09%09}%0A%0A%09%09return addon;%0A%09},%0A%0A%09// Bug 1512436 - Add new install location for built in search web extensions (Firefox 67+)%0A%09// https://bugzilla.mozilla.org/show_bug.cgi?id=1512436%0A%09// https://hg.mozilla.org/mozilla-central/diff/e3e75697e98c/toolkit/mozapps/extensions/internal/XPIProvider.jsm%23l1.396%0A%09//loadScope(addon, file) {%0A%09loadScope(addon, file = addon.file || addon._sourceBundle) {%0A%0A%09%09let uri = getURIForResourceInFile(file, "bootstrap.js").spec;%0A%09%09let principal = Services.scriptSecurityManager.getSystemPrincipal();%0A%0A%09%09let sandbox = new Cu.Sandbox(principal, {%0A%09%09%09sandboxName: uri,%0A%09%09%09addonId: addon.id,%0A%09%09%09wantGlobalProperties: ["ChromeUtils"],%0A%09%09%09metadata: { addonID: addon.id, URI: uri },%0A%09%09});%0A%0A%09%09try {%0A%09%09%09Object.assign(sandbox, BOOTSTRAP_REASONS);%0A%0A%09%09%09XPCOMUtils.defineLazyGetter(%0A%09%09%09%09sandbox, "console", () => new ConsoleAPI({ consoleID: %60addon/%24{addon.id}%60 })%0A%09%09%09);%0A%09%09%09Services.scriptloader.loadSubScript(uri, sandbox);%0A%0A%09%09} catch (e) {%0A%09%09%09logger.warn(%60Error loading bootstrap.js for %24{addon.id}%60, e);%0A%09%09}%0A%0A%09%09function findMethod(name) {%0A%09%09%09if (sandbox.name) {%0A%09%09%09%09return sandbox.name;%0A%09%09%09}%0A%09%09%09try {%0A%09%09%09%09let method = Cu.evalInSandbox(name, sandbox);%0A%09%09%09%09return method;%0A%09%09%09} catch (err) { }%0A%0A%09%09%09return () => {%0A%09%09%09%09logger.warn(%60Add-on %24{addon.id} is missing bootstrap method %24{name}%60);%0A%09%09%09};%0A%09%09}%0A%0A%09%09let install = findMethod("install");%0A%09%09let uninstall = findMethod("uninstall");%0A%09%09let startup = findMethod("startup");%0A%09%09let shutdown = findMethod("shutdown");%0A%0A%09%09return {%0A%09%09%09install: (...args) => install(...args),%0A%09%09%09uninstall: (...args) => uninstall(...args),%0A%0A%09%09%09startup(...args) {%0A%09%09%09%09if (addon.type == "extension") {%0A%09%09%09%09%09logger.debug(%60Registering manifest for %24{file.path}\n%60);%0A%09%09%09%09%09Components.manager.addBootstrappedManifestLocation(file);%0A%09%09%09%09}%0A%09%09%09%09return startup(...args);%0A%09%09%09},%0A%0A%09%09%09shutdown(data, reason) {%0A%09%09%09%09try {%0A%09%09%09%09%09return shutdown(data, reason);%0A%09%09%09%09} catch (err) {%0A%09%09%09%09%09throw err;%0A%09%09%09%09} finally {%0A%09%09%09%09%09if (reason != BOOTSTRAP_REASONS.APP_SHUTDOWN) {%0A%09%09%09%09%09%09logger.debug(%60Removing manifest for %24{file.path}\n%60);%0A%09%09%09%09%09%09Components.manager.removeBootstrappedManifestLocation(file);%0A%09%09%09%09%09}%0A%09%09%09%09}%0A%09%09%09},%0A%09%09};%0A%09},%0A};%0A// fim BootstrapLoader.jsm%0A%0A%0AAddonManager.addExternalExtensionLoader(BootstrapLoader);%0AObject.defineProperty(%0A%09AddonInternal.prototype,%0A%09"providesUpdatesSecurely",%0A%09{enumerable: true, value: true}%0A);%0A
        `.trim(), new Cu.Sandbox(Cu.getObjectPrincipal(this), {wantGlobalProperties: ["ChromeUtils", "atob"]}));
} catch(ex) {Cu.reportError(ex);}

lockPref("general.useragent.override.youtube.com", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0 PaleMoon/27.4.2");
lockPref("browser.download.panel.shown", false);
lockPref("dom.storageManager.enabled", false);  
lockPref("dom.push.enabled", false); 
lockPref("dom.webnotifications.enabled", false);
lockPref("reader.parse-on-load.enabled", false);
lockPref("security.insecure_field_warning.contextual.enabled", false); 
lockPref("security.insecure_password.ui.enabled", false);
lockPref("signon.autofillForms.http", true);   
lockPref("toolkit.telemetry.enabled", false); 
lockPref("app.update.service.enabled", false);
lockPref("plugin.load_flash_only", false);
lockPref("network.predictor.cleaned-up", true); 
lockPref("browser.tabs.remote.autostart", false);
lockPref("alerts.showFavicons", true);  
lockPref("toolkit.cosmeticAnimations.enabled", false);  


И этот код без ломки MOZ_REQUIRE_SIGNING и MOZ_ALLOW_LEGACY_EXTENSIONS, это можно в AppConstants.jsm рихтануть, хотя можно и код оставить в тот же bootstrap-loader.js ....Ну, там, угрожающие надписи еще убрать в about:addons, это мелочь и xpinstall.signatures.required=false,extensions.legacy.enabled=true, короче, меньше пены, больше креатива....

Отредактировано drage2 (24-03-2019 11:59:50)

Отсутствует

 

№1317525-03-2019 16:50:04

rubel
Участник
 
Группа: Members
Откуда: г.Самара
Зарегистрирован: 10-05-2005
Сообщений: 367
UA: Firefox 66.0

Re: Custom Buttons

Andrey_Krropotkin
Ваша кнопка Перевод  перестала переводить из Перевод из буфера в FF  66. Может поправите её?

Отредактировано rubel (27-03-2019 06:33:36)

Отсутствует

 

Board footer

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