Что то с кодировкой в UTF-8 выходного файла не получается, не пойму где ее поменять можно ( в persist, saveURI или еще где-то)
Я почему-то думал, что это кодировка всего выходного файла, меняю в AkelPad, в нем удобнее: сохранить как - снизу в выпадающем меню выбрать UTF-8, снять птичку BOM. Я ошибаюсь?
Отсутствует
shadow_user не об этом речь, надо чтобы не менять в редакторе, а открываешь редактор, а там уже нужная кодировка.
Отсутствует
открываешь редактор, а там уже нужная кодировка.
NotePad++: Опции -> Настройки -> Новый документ -> Синтаксис по умолч.: - CSS (или ...txt, batch...) -> Кодировка - UTF-8
Опции -> Настройки -> Разное -> Автоопределение кодировки - снять птичку.
Теперь при сохранении или открытии файлов .css, .txt, .bat автоматом будет устанавливаться кодировка UTF-8. У меня так и это работает. Тоже не то?
Отредактировано shadow_user (09-03-2020 11:50:19)
Отсутствует
shadow_user зачем мне его открывать? Я скачал скрипт и он уже должен работать, а работать нормально будет только в utf8.
Отсутствует
зачем мне его открывать?
Может, и незачем. А если он сохранен в другой кодировке? Открыл, посмотрел, перекодировал в utf-8. Грамотные старожилы подтянутся, может, направят в правильном направлении.
Отсутствует
«Merge Day»
Трудно поверить, но, похоже, Custom Buttons за этот цикл не сломали.
Таким образом, остаётся десятка, обновление не требуется.
̣ ̣
Если тестирую браузер нужен AGENT_SHEET, если сайт - USER_SHEET
Странное утверждение. AGENT_SHEET нужен для стилизации NAC.
В любом случае, можно сделать две (или даже все три) кнопки для preview разных типов.
Кстати, AGENT_SHEET preview может глючить, например для NAC-тултипа браузера.
Код:
Посмотрел. Да, вполне подойдёт. Метод используется только в одном месте
для получения ссылки на gBrowser. Сам скрипт, конечно, для однопроцессного режима.
В saveURI() передаётся, почему-то, 8 аргументов, хотя idl говорит, что нужно 9.
Отсутствует
Трудно поверить, но, похоже, Custom Buttons за этот цикл не сломали.
Таким образом, остаётся десятка, обновление не требуется.
Dumby у меня что-то никак не появляется в профиле с 73его на 74b9-dev и найтли тоже от 090320
пытаюсь переустановить, пишет:
74b9-dev
Отсутствует
на 74b9-dev и найтли тоже от 090320
пытаюсь переустановить
Я собрал портаблы указаных версий и на обе CB установился без проблем.
Сообщение на скринах довольно экзотическое. Обычно, если что-то
пошло не так, то пишет типа «повреждено» или «непроверено»,
но чтобы «несовместимо», — как-то даже не припомню такого в истории
нынешних последних времён.
Помимо проверки установки на чистых профиле/портабл/инсталляции,
возможно, будет представлять интерес то, что во время установки
пишет консоль, если включить extensions.logging.enabled
Отсутствует
Dumby
Упал аддон в 74
https://www.upload.ee/files/11249735/fl … u.xpi.html
Отсутствует
Dumby
вобщем проблема локализована, в config.js подгружался арсенал userchromeJS раньше, чем твоя "рефлексия" с nsvo,
в итоге оказалась интересная штука, я закомментил все, без чего можно обойтись, по крайней мере в моей конфигурации
// try {(nsvo => { var o = Cu.getGlobalForObject(nsvo).Object, {freeze} = o, NEW; o.freeze = obj => { if (Components.stack.caller.filename != "resource://gre/modules/AppConstants.jsm") return freeze(obj); obj.MOZ_GOOGLE_LOCATION_SERVICE_API_KEY = false; // что угодно из AppConstants.jsm //MOZ_REQUIRE_SIGNING if ((NEW = "MOZ_GOOGLE_SAFEBROWSING_API_KEY" in obj)) // что угодно из AppConstants.jsm //MOZ_ALLOW_ADDON_SIDELOAD // lockPref("extensions.experiments.enabled", true); // else // obj.MOZ_ALLOW_LEGACY_EXTENSIONS = true, // lockPref("extensions.legacy.enabled", true); return (o.freeze = freeze)(obj); } //lockPref("xpinstall.signatures.required", false); //lockPref("extensions.langpacks.signatures.required", false); nsvo = Cu.import("resource://gre/modules/addons/XPIInstall.jsm", {}); var shouldVerify = nsvo.shouldVerifySignedState; nsvo.shouldVerifySignedState = addon => !addon.id && shouldVerify(addon); if (NEW) nsvo.XPIDatabase.isDisabledLegacy = () => false; })(Cu.import("resource://gre/modules/WebRequestCommon.jsm", {}));} catch(ex) {Cu.reportError(ex);} // load UC try { let { classes: Cc, interfaces: Ci, manager: Cm, utils: Cu } = Components; let cmanifest = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get('UChrm', Ci.nsIFile); cmanifest.append('boulderdash'); cmanifest.append('chrome.manifest'); if(cmanifest.exists()){ Cm.QueryInterface(Ci.nsIComponentRegistrar).autoRegister(cmanifest); Cu.import('chrome://userchromejs/content/ucm.jsm'); } } catch(ex) {};
Отредактировано dezhnev (10-03-2020 20:32:00)
Отсутствует
Dumby посмотри пожалуйста кнопку, правленой раньше тобой
// http://infocatcher.ucoz.net/js/cb/switchKeybLayout.js // https://github.com/Infocatcher/Custom_Buttons/tree/master/Switch_Keyboard_Layout // Switch Keyboard Layout button for Custom Buttons // (code for "code" section) // (c) Infocatcher 2009, 2013-2014 // version 0.2.0 - 2014-10-20 // Convert text, typed in wrong keyboard layout. // Configured for Russian <-> English. (keybUtils => { var btn = this; var listener = { handleEvent(e) { if(e.target != btn) return; e.preventDefault(); e.stopPropagation(); this.switch(); }, switch() { var br = document.activeElement; br && br.localName == "browser" && br.isRemoteBrowser ? br.messageManager.loadFrameScript(this.url, false) : this.keybUtils.switchSelKeybLayout(); }, get url() { delete this.url; return this.url = `data:;charset=utf-8,(${ encodeURIComponent(keybUtils) }).switchSelKeybLayout()`; }, get keybUtils() { delete this.keybUtils; var url = "data:;charset=utf-8,this.keybUtils = " + encodeURIComponent(keybUtils); Services.scriptloader.loadSubScript(url, this); this.keybUtils.button = btn; this.keybUtils.getFocusedElement = function(_subCall, _focusFixed) { if( !_focusFixed && "closeMenus" in window && document.commandDispatcher.focusedElement == this.button ) { closeMenus(this.button); setTimeout(function(_this) { _this.switchSelKeybLayout(_subCall, true); }, 0, this); return; } return document.commandDispatcher.focusedElement; } return this.keybUtils; } }; if(btn instanceof XULElement && addEventListener.length > 3) { addEventListener("command", listener, true, this.parentNode); } listener.switch(); })(`{ //== Options noSelBehavior: { // Shift+Home ctrlKey: false, altKey: false, shiftKey: true, metaKey: false, keyCode: KeyEvent.DOM_VK_HOME, charCode: 0 }, // 0 - do nothing // 1 - convert all text // Or use object like following to simulate "keypress" event: convTableForward: { // ru -> en "\\"": "@", ":": "^", ";": "$", "?": "&", ",": "?", "/": "|", ".": "/", "э": "'", "б": ",", "ю": ".", "Ж": ":", "ж": ";", "Б": "<", "Ю": ">", "Э": "\\"", "х": "[", "ъ": "]", "ё": "\`", "Х": "{", "Ъ": "}", "Ё": "~", "№": "#", "Ф": "A", "ф": "a", "И": "B", "и": "b", "С": "C", "с": "c", "В": "D", "в": "d", "У": "E", "у": "e", "А": "F", "а": "f", "П": "G", "п": "g", "Р": "H", "р": "h", "Ш": "I", "ш": "i", "О": "J", "о": "j", "Л": "K", "л": "k", "Д": "L", "д": "l", "Ь": "M", "ь": "m", "Т": "N", "т": "n", "Щ": "O", "щ": "o", "З": "P", "з": "p", "Й": "Q", "й": "q", "К": "R", "к": "r", "Ы": "S", "ы": "s", "Е": "T", "е": "t", "Г": "U", "г": "u", "М": "V", "м": "v", "Ц": "W", "ц": "w", "Ч": "X", "ч": "x", "Н": "Y", "н": "y", "Я": "Z", "я": "z", __proto__: null }, //== End of options get convTableBackward() { var ctb = { __proto__: null }; var ctf = this.convTableForward; for(var c in ctf) ctb[ctf[c]] = c; delete this.convTableBackward; return this.convTableBackward = ctb; }, inPrimaryLayout: function(s) { for(var i = 0, l = s.length; i < l; ++i) { var c = s.charAt(i); if(c in this.convTableForward) return true; if(c in this.convTableBackward) return false; } return false; }, switchKeybLayout: function(s, convTable) { var res = ""; for(var i = 0, l = s.length; i < l; ++i) { var c = s.charAt(i); res += c in convTable ? convTable[c] : c; } return res; }, getFocusedElement: function() { return Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager) .getFocusedElementForWindow(content, true, {}); }, switchSelKeybLayout: function(_subCall, _focusFixed) { var fe = this.getFocusedElement(_subCall, _focusFixed); if(!fe) return; if(fe instanceof HTMLInputElement || fe instanceof HTMLTextAreaElement) { var ta = fe; try { var val = ta.value; var sel = val.substring(ta.selectionStart, ta.selectionEnd); } catch(e) { // Non-text HTMLInputElement return; } if(!sel && val && this.noSelBehavior && !_subCall) { if(this.noSelBehavior == 1) { ta.selectionStart = 0; ta.selectionEnd = val.length; sel = val; } else { this.handleNoSel(ta); return; } } if(!sel) return; var res = this.switchKeybLayout( sel, this.inPrimaryLayout(sel) ? this.convTableForward : this.convTableBackward ); if(res != sel) this.insertText(ta, res); } else if(fe.contentEditable == "true") { var doc = fe.ownerDocument; var docURI = doc.documentURI; if( docURI.substr(0, 5) == "data:" && docURI.indexOf("chrome://browser/skin/devtools/") != -1 ) { //~ todo: seems like we only can use paste from clipboard here... return; } var sel = doc.defaultView.getSelection(); var rng = sel.rangeCount && sel.getRangeAt(0); var tmpNode; if(!rng || rng.collapsed) { if(!this.noSelBehavior || _subCall) return; if(this.noSelBehavior == 1) { var r = doc.createRange(); r.selectNodeContents(fe); sel.removeAllRanges(); sel.addRange(r); tmpNode = fe.cloneNode(true); } else { this.handleNoSel(fe); return; } } else { tmpNode = doc.createElementNS("http://www.w3.org/1999/xhtml", "div"); tmpNode.appendChild(rng.cloneContents()); } var orig = tmpNode.innerHTML; var convTable = this.inPrimaryLayout(tmpNode.textContent) ? this.convTableForward : this.convTableBackward; var _this = this; var parseChildNodes = function(node) { if(node instanceof Element) { var childNodes = node.childNodes; for(var i = childNodes.length - 1; i >= 0; --i) parseChildNodes(childNodes[i]); } else if(node.nodeType == node.TEXT_NODE) { var text = node.nodeValue; var newText = _this.switchKeybLayout(node.nodeValue, convTable); if(newText != text) node.parentNode.replaceChild(doc.createTextNode(newText), node); } } parseChildNodes(tmpNode); var res = tmpNode.innerHTML; if(res != orig) doc.execCommand("insertHTML", false, res); } }, handleNoSel: function(node) { this.select(node); this.switchSelKeybLayout(true); }, select: function(node) { var e = this.noSelBehavior; if(!e || typeof e != "object") return; var evt = node.ownerDocument.createEvent("KeyboardEvent"); evt.initKeyEvent( "keypress", true /*bubbles*/, true /*cancelable*/, node.ownerDocument.defaultView, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.keyCode, e.charCode ); node.dispatchEvent(evt); }, insertText: function(ta, text) { //var editor = ta.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor var editor = ta.editor .QueryInterface(Components.interfaces.nsIPlaintextEditor); if(editor.flags & editor.eEditorReadonlyMask) return; var sTop = ta.scrollTop; var sHeight = ta.scrollHeight; var sLeft = ta.scrollLeft; // var sWidth = ta.scrollWidth; if(text) editor.insertText(text); else editor.deleteSelection(0, 0); ta.scrollTop = sTop + (ta.scrollHeight - sHeight); ta.scrollLeft = sLeft; // + (ta.scrollWidth - sWidth); } }`);
Отсутствует
как не хватает функционала этой кнопки в дополнениях для новых версий лисы, их просто нет
привык к ней безумно, а в новом фоксе у меня какие-то постоянные траблы в целомс CB (скорее руки кривые)
Dumby где-то в теме писал, что можно код кнопки завернуть в такое дополнение.
Подскажите как или, если кто сможет сам, помогите создать такое дополнение для всех в радость))
Отсутствует
Упал аддон в 74
Не вижу. Скачал, установил в 74.0, нормально работает,
ну кроме как в той части, которая пострадала от того,
что ты, зачем-то, выбросил button.css
Приципиальное разрешение на paxmod'ы привязали
к подписячему флагу, а пользовательское произволение
реализуется посредством настройки extensions.experiments.enabled
А вот расширения запрещены полностью и для всех каналов обновления.
Конфигурация дадена. Если не нравится, тогда используй другую.
Если не нравится JS-воздействие как таковое, тогда обеспечь
аналогичное правкой omni.ja
Но если ничего не сделать, тогда конечо, bootstrap-расширения
(а другие и невозможны уже давно) работать не будут.
Could not convert JavaScript argument arg 0 [nsISupports.QueryInterface]
nsIPlaintextEditor выбросили из Ci, а его функционал переместили в nsIEditor
Если обратная совместимость не нужна, то можно удалить
.QueryInterface(Components.interfaces.nsIPlaintextEditor);
а если нужна, то заменить, например, на
.QueryInterface(Components.interfaces.nsIPlaintextEditor || Ci.nsIEditor);
Отсутствует
Dumby
Да оно даже не устанавливается ... Код новый config.js есть?
extensions.experiments.enabled -true
где в omni.ja рихтовать ? Вроде все как всегда там отрихтовал...
Рихтанул кардинально ...Установилось...
Отредактировано solombala (10-03-2020 23:36:14)
Отсутствует
solombala
попробуй этот, фишка в том, что первый блок не трогай, а вниз ставь все свое что бы там ни было
// try {(nsvo => { var o = Cu.getGlobalForObject(nsvo).Object, {freeze} = o, NEW; o.freeze = obj => { if (Components.stack.caller.filename != "resource://gre/modules/AppConstants.jsm") return freeze(obj); obj.MOZ_REQUIRE_SIGNING = false; if ((NEW = "MOZ_ALLOW_ADDON_SIDELOAD" in obj)) lockPref("extensions.experiments.enabled", true); else obj.MOZ_ALLOW_LEGACY_EXTENSIONS = true, lockPref("extensions.legacy.enabled", true); return (o.freeze = freeze)(obj); } lockPref("xpinstall.signatures.required", false); lockPref("extensions.langpacks.signatures.required", false); nsvo = Cu.import("resource://gre/modules/addons/XPIInstall.jsm", {}); var shouldVerify = nsvo.shouldVerifySignedState; nsvo.shouldVerifySignedState = addon => !addon.id && shouldVerify(addon); if (NEW) nsvo.XPIDatabase.isDisabledLegacy = () => false; })(Cu.import("resource://gre/modules/WebRequestCommon.jsm", {}));} catch(ex) {Cu.reportError(ex);} // try {({ ids: [ "custombuttons@xsms.org", ], init(xrt) { if (xrt.inSafeMode) return; Cu.import("resource://gre/modules/addons/XPIProvider.jsm", this); var load = async file => { var rootURI = this.XPIInternal.getURIForResourceInFile(file, ""); Cu.import(rootURI.resolve("startup.jsm"), {}).start(rootURI); } var proto = this.XPIInternal.BootstrapScope.prototype; var func = proto._beforeCallBootstrapMethod; proto._beforeCallBootstrapMethod = () => { proto._beforeCallBootstrapMethod = func; for(var addon of this.XPIInternal.XPIStates.enabledAddons()) this.ids.includes(addon.id) && !addon.loader && load(addon.file); } } }).init(Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime));} catch(ex) {Cu.reportError(ex);} // 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%0A%09%09%09// https://github.com/xiaoxiaoflood/firefox-scripts/commit/b509dd0089dc7245e9797e0068b8fcff6ae3c776%0A%09%09%09//uninstall: (...args) => uninstall(...args),%0A%09%09%09uninstall(...args) {%0A%09%09%09%09var res = uninstall(...args);%0A%09%09%09%09// Forget any cached files we might've had from this extension.%0A%09%09%09%09Services.obs.notifyObservers(null, "startupcache-invalidate");%0A%09%09%09%09return res;%0A%09%09%09},%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);}
Отсутствует
Inko7 о какой кнопке речь?
Отсутствует
dezhnev
От это - то шо надо! Кстати, этот код можно сократить? В AppConstants.jsm уже правил и в префке тоже ( lockPref("extensions.legacy.enabled", true); и т.д)
nsvo = Cu.import("resource://gre/modules/addons/XPIInstall.jsm", {});
var shouldVerify = nsvo.shouldVerifySignedState;
nsvo.shouldVerifySignedState = addon => !addon.id && shouldVerify(addon);
if (NEW) nsvo.XPIDatabase.isDisabledLegacy = () => false;
})(Cu.import("resource://gre/modules/WebRequestCommon.jsm", {}));}
catch(ex) {Cu.reportError(ex);}
Отредактировано solombala (11-03-2020 12:33:03)
Отсутствует
Dumby посмотри пожалуйста код, что то не получается. В блоке saveScript - если XMLHttpRequest() сделать асинхронным, то все рушится. Может есть вариант по другому сделать сохранение.
(function() { // Включены ли уведомления после сохранения? var notificationsAfterInstall = true; // Загружается ли скрипт после сохранения (запускать не нужно)? Поддерживается только .uc.js, некоторые скрипты проблематичны. var runWithoutRestart = true; let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; if (!window.Services) Cu.import("resource://gre/modules/Services.jsm"); const RE_USERCHROME_JS = /\.uc(?:-\d+)?\.(?:js|xul)$|userChrome\.js$/i; const RE_CONTENTTYPE = /text\/html/i; var ns = window.saveUserChromeJS = { init: function() { // добавить в contentAreaContextMenu if ( document.getElementById("uc-install-menu") ) return; var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; var icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAICAAP//AICAgMDAwP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcj7VkAAABfdFJOU/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8Ak5pfLAAAAAlwSFlzAAAOwwAADsMBx2+oZAAAAFxJREFUKFNljgEOwCAIAwuF/395RWXMrDExHLQA3gKYpVXojwPo6SpewDSzAHGAXvWpkQYagNSWN2EyfGUM+G/RQWZFOnSt9AZMR3nGwggivqF1Q12xQVzavRHwALQIAv2bDRzYAAAAAElFTkSuQmCC"; var contextMenu = document.getElementById("contentAreaContextMenu"); var menuitem = document.createElementNS(xulns, "menuitem"); menuitem.setAttribute("id", "uc-install-menu"); menuitem.setAttribute("label", "Установить для userChromeJS"); menuitem.setAttribute("class", "menuitem-iconic"); menuitem.setAttribute("image", icon); menuitem.setAttribute("accessKey", "I"); menuitem.setAttribute("oncommand", "saveUserChromeJS.saveScript(gContextMenu.linkURL)"); contextMenu.insertBefore(menuitem, contextMenu.firstChild); contextMenu.addEventListener("popupshowing", this, false); this._menuitem = menuitem; }, handleEvent: function(event){ switch(event.type){ case "popupshowing": if (event.target != event.currentTarget) return; if(gContextMenu.onLink){ this._menuitem.hidden = !RE_USERCHROME_JS.test(gContextMenu.linkURL); }else{ this._menuitem.hidden = true; } break; } }, saveScript: function(url) { var name, fileName, fileExt, charset; name = name && name[1] ? name[1] : decodeURIComponent(url.split("/").pop()); fileName = name.replace(/\.uc\.(js|xul)$|$/i, ".uc.$1").replace(/\s/g, '_'); if (fileName.match(/\.uc\.$/i)) { // Исправить имя var m = url.match(/\.(js|xul)$/); if (m) fileName += m[1]; } charset = "UTF-8"; var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); var err = false; try { fp.init(window, "", Ci.nsIFilePicker.modeSave); } catch(e) { fp.init(ns.getMostRecentWindow(), "", Ci.nsIFilePicker.modeSave); err = true; Application.console.log('SaveUserChromeJS.uc.js - error catched (A)'); }; var SCRIPTS_FOLDER = Services.dirsvc.get("UChrm", Ci.nsIFile); var xhr = new XMLHttpRequest(); var url2 = url.replace("github", "raw.githubusercontent").replace("\/blob", " "); xhr.open('GET', url2, false); xhr.send(); if (xhr.status == 200) { var uc = Components.classes['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.nsIScriptableUnicodeConverter); uc.charset = 'utf-8'; var text = uc.ConvertFromUnicode(xhr.responseText); } fp.displayDirectory = SCRIPTS_FOLDER; fp.appendFilters(Ci.nsIFilePicker.filterAll); fp.defaultExtension = fileExt; fp.defaultString = fileName; var nsIFilePicker = Components.interfaces.nsIFilePicker; fp.open(function (rv) { if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { var foStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); foStream.init(fp.file, 0x02|0x20|0x08, 0666, 0); foStream.write(text, text.length); foStream.close(); if(notificationsAfterInstall){ var win = err ? ns.getMostRecentWindow() : window; win.setTimeout(function(){ fileExt1 = name.match(/\.uc\.(js|xul)$/i); fileExt1 = fileExt && fileExt[1] ? fileExt[1] : "js"; ns.showInstallMessage({ fileExt: fileExt1, fileName: fileName, file: fp.file, charset: charset }); }, 100); } } }); }, showInstallMessage: function(info){ var isRun = (info.fileExt == "js"); var mainAction, secondActions; if(runWithoutRestart && isRun){ mainAction = { label: "Выполнить без перезапуска.", accessKey: "a", callback: function(){ var dir = Services.dirsvc.get("UChrm", Ci.nsIFile); dir.initWithPath(dir.path + "\\" + info.fileName); var url = Services.io.newFileURI(dir).spec; let context = {}; Services.scriptloader.loadSubScript( url, context, "UTF-8"); var showedMsg1 = ns.popupNotification({ id: "userchromejs1-install-popup-notification", message: "Скрипт запущен", options: { removeOnDismissal: true, persistWhileVisible: true } }); } }; secondActions = [{ label: "Перезагрузите сейчас", accessKey: "s", callback: ns.restartApp }]; }else{ mainAction = { label: "Перезагрузите сейчас", accessKey: "s", callback: ns.restartApp }; secondActions = null; } var showedMsg = ns.popupNotification({ id: "userchromejs-install-popup-notification", message: "'" + info.fileName + "' Установка завершена.", mainAction: mainAction, secondActions: secondActions, options: { removeOnDismissal: true, persistWhileVisible: true } }); }, popupNotification: function(details){ var win = ns.getMostRecentWindow(); if (win && win.PopupNotifications) { win.PopupNotifications.show( win.gBrowser.selectedBrowser, details.id, details.message, "", details.mainAction, details.secondActions, details.options); return true; } return false; }, getMostRecentWindow: function(){ return Services.wm.getMostRecentWindow("navigator:browser") }, restartApp: function() { Services.startup.quit(Services.startup.eAttemptQuit | Services.startup.eRestart) } }; function log(arg){ Application.console.log("[SaveUserChromeJS]" + arg);} })(); window.saveUserChromeJS.init();
Отсутствует
Dumby
СВ новый какой ? =base64 не хочет прописывать , или код какой?
Нашел СВ 10, ОК! Нужен код "Удалить куки " Нет, не куки , "активные сеансы" ...
"Смена Языка кириллица-латиница в поиске" - того в 74...Кто мастерил? Князь- анархист?
Отредактировано solombala (13-03-2020 11:11:25)
Отсутствует
для 68й что то не найду
В add_toolbar_buttons есть такая кнопка.
В крайнем случае можно попробовать сделать экстракт для вкладки Код.
var wt = "Toolkit:PasswordManager"; var win = Services.wm.getMostRecentWindow(wt); var uri = gBrowser.currentURI; try { var filter = Services.eTLD.getBaseDomain(uri); } catch(ex) { var filter = uri.asciiHost; } var setFilter = e => (win || e.target.ownerGlobal).setFilter(filter); if (win) win.focus(), setFilter(); else openDialog( "chrome://passwordmgr/content/passwordManager.xul", wt, "chrome,dialog=no,centerscreen,resizable" ).addEventListener("pageshow", setFilter, {once: true});
В блоке saveScript - если XMLHttpRequest() сделать асинхронным, то все рушится.
Так делал?
//xhr.open('GET', url2, false); //xhr.send(); //if (xhr.status == 200) { xhr.open('GET', url2, true); xhr.onloadend = () => { if (xhr.status == 200) { // и всё дальнейшее } xhr.send();
Нужен код "Удалить куки " Нет, не куки , "активные сеансы"
Я фик знает, мне их взять негде. Может так попробуй
ChromeUtils.import("resource:///modules/Sanitizer.jsm")
.Sanitizer.sanitize(["sessions"]);
Отсутствует