cambriancn
小狐狸
小狐狸
  • UID57310
  • 注册日期2019-10-10
  • 最后登录2022-10-05
  • 发帖数28
  • 经验30枚
  • 威望0点
  • 贡献值16点
  • 好评度1点
阅读:1616回复:6

大牛帮忙修复一下 附加组件页增强.uc ?

楼主#
更多 发布于:2020-05-09 12:15
cc @lonely_8  或者其他大牛,帮忙看看这个能否修复?



// ==UserScript==
// @name         AddonsPage.uc.js
// @description  附件组件页面右键新增查看所在目录,详细信息页面新增安装地址或路径,新增 uc脚本管理页面。
// @author       ywzhaiqi
// @include      main
// @charset      utf-8
// @version      2018.06.27
// @downloadURL  https://raw.github.com/ywzhaiqi/userChromeJS/master/AddonsPage/AddonsPage.uc.js
// @homepageURL  https://github.com/ywzhaiqi/userChromeJS/tree/master/AddonsPage
// @reviewURL    http://bbs.kafan.cn/thread-1617407-1-1.html
// @optionsURL   about:config?filter=view_source.editor.path
// @note         - 附件组件页面右键新增查看所在目录(支持扩展、主题、插件)、复制名字。Greasemonkey、Scriptish 自带已经存在
// @note         - 附件组件详细信息页面新增GM脚本、扩展、主题安装地址和插件路径,右键即复制
// @note         - 新增 uc脚本管理页面
// @note         - 右键菜单 "查看附加组件" 需要 DOM Inspector
// @note         - uc脚本管理界面
// @note         - 启用禁用需要 rebuild_userChrome.uc.xul
// @note         - 编辑命令需要首先设置 view_source.editor.path 的路径
// @note         - 图标请自行添加样式,详细信息见主页
// @note         其它信息见主页
// ==/UserScript==
 
location.href.startsWith('chrome://browser/content/browser.x') && (function(){
 
    var iconURL = "";  // uc Skriptlisten-Symbol
 
    var Config = {
        debug: 1,  // 1 则uc管理界面右键菜单会有 "重载 uc 脚本" 的菜单
        detailView: 1,  // Auf Details-Seite Installation-Link hinzufügen
    };
 
    if(window.AM_Helper){  // Debugging ändern, neu laden ohne neu zu starten
        window.AM_Helper.uninit();
        delete window.AM_Helper;
    }
    if(window.userChromeJSAddon){
        window.userChromeJSAddon.uninit();
        delete window.userChromeJSAddon;
    }
 
    Cu.import("resource://gre/modules/Services.jsm");
    Cu.import("resource://gre/modules/AddonManager.jsm");
 
    let isCN = false;
    try {
        isCN = Services.prefs.getCharPref("general.useragent.locale").indexOf("zh") != -1;
    } catch (e) {
        try {
            isCN = Services.prefs.getCharPref("intl.locale.requested").indexOf("zh") != -1;
        } catch (e) {
        }
    }
 
    var ApplyPatchForScript = (function(){
        const USO_URL_RE = /(^https?:\/\/userscripts.org.*\/scripts\/source\/\d+)\.\w+\.js$/i;
 
        const GFO_URL_RE_1 = /(^https?:\/\/greasyfork.org\/scripts\/code\/\w+)\.\w+\.js$/i;
        const GFO_URL_RE_2 = /(^https?:\/\/greasyfork.org\/scripts\/[^\/]+\/)code[\.\/].*\w+\.js$/i;
 
        // (http://binux.github.io/ThunderLixianExporter/)master/ThunderLixianExporter.user.js
        const GITHUB_URL_RE_1 = /(^https?:\/\/\w+.github.io\/\w+\/)master\/.*.*\w+\.js$/i;
        // 从   https://raw.githubusercontent.com/ywzhaiqi/userscript/master/noNoticetitleflashOnBBS.user.js
        // 转为 https://github.com/ywzhaiqi/userscript/blob/master/noNoticetitleflashOnBBS.user.js
        const GITHUB_URL_RE_2 = /(^https?:\/\/raw.githubusercontent.com\/.*?\/master\/.*\.user\.js$)/i;
 
        function getScriptHomeURL(downURL) {
            var url;
            if (downURL && downURL.startsWith('http')) {
                if (USO_URL_RE.test(downURL)) {
                    url = RegExp.$1.replace(/source/, "show");
                } else if (GFO_URL_RE_1.test(downURL)) {
                    url = RegExp.$1;
                } else if (GFO_URL_RE_2.test(downURL)) {
                    url = RegExp.$1;
                } else if (GITHUB_URL_RE_1.test(downURL)) {
                    url = RegExp.$1;
                } else if (GITHUB_URL_RE_2.test(downURL)) {
                    url = RegExp.$1.replace('raw.githubusercontent.com', 'github.com')
                            .replace('/master/', '/blob/master/');
                }
            }
            return url ? decodeURIComponent(url) : null;
        }
 
        function addHomePage(){
            // 添加 Scriptish 脚本的主页
            if (window.Scriptish_config) {
                Scriptish_config.scripts.forEach(function(script){
                    if(script.homepageURL) return;
 
                    var url = script.updateURL || script.downloadURL;
                    script.homepageURL = getScriptHomeURL(url);
                });
            }
 
            // 添加 Greasemonkey 脚本的主页
            AddonManager.getAddonsByTypes(['greasemonkey-user-script'], function (aAddons) {
                aAddons.forEach(function (aAddon) {
                    if (aAddon.homepageURL) return;
 
                    var url = aAddon._script._downloadURL || aAddon._script._updateURL;
                    var homepageURL = getScriptHomeURL(url);
                    if (homepageURL) {
                        aAddon.homepageURL = homepageURL;
                    } else {
                        // console.log(aAddon.name, url);
                    }
                });
            });
        }
 
        return {
            init: addHomePage
        }
    })();
 
    setTimeout(function(){
        ApplyPatchForScript.init();
    }, 2000);
 
    window.AM_Helper = {
        init: function(){
            document.addEventListener("DOMContentLoaded", this, false);
            this.platformVersion = parseFloat(Services.appinfo.platformVersion);
        },
        uninit: function(){
            document.removeEventListener("DOMContentLoaded", this, false);
        },
        handleEvent: function(event){
            switch(event.type){
                case "DOMContentLoaded":
                    var doc = event.target;
                    var win = doc.defaultView;
 
                    if (["about:addons","chrome://mozapps/content/extensions/extensions.xul"].indexOf(doc.URL) == -1)
                        return;
 
                    this.addPopupMenu(doc);
 
                    // 给菜单调用
                    win.AM_Helper = AM_Helper;
                    this.win = win;
 
                    if (Config.detailView) {
                        var self = this;
                        var observer = new MutationObserver(function(e) {
                            e = e[e.length-1];
                            if(e.attributeName == "loading") {
                                var doc = e.target.ownerDocument;
                                self.setUrlOrPath(doc);
                            }
                        });
                        observer.observe(doc.getElementById("detail-view"), {attributes: true});
                    }
                    break;
                case "popupshowing":
                    if(this.win.document.popupNode){
                        this.getAddon(this.win.document.popupNode.value,
                            this.setItemsAttributes,
                            event);
                    }
                    break;
            }
        },
        addPopupMenu: function(doc){
            var ins = doc.getElementById("menuitem_uninstallItem");
            if(!ins) return;
 
            ins = ins.nextSibling;
            var popup = ins.parentNode;
 
            var menuitem = $C("menuseparator", {
                id: "AM-separator-1"
            }, doc);
            popup.insertBefore(menuitem, ins);
 
            menuitem = $C("menuitem", {
                id: "AM-inspect-addon",
                label: isCN ? "查看附加组件" : "Inspect Addon",
                accesskey: "i",
                tooltipText: isCN ? "调用 DOM Inspector 查看 addon 对象" : "Addon mit Dom Inspector inspizieren",
                oncommand: "AM_Helper.getAddon(AM_Helper.getPopupNode(this).value, AM_Helper.inspectAddon);"
            }, doc);
            popup.insertBefore(menuitem, ins);
 
            menuitem = $C("menuitem", {
                id: "AM-edit-script",
                label: isCN ? "编辑" : "Edit",
                accesskey: "e",
                hidden: true,
                oncommand: "AM_Helper.getAddon(AM_Helper.getPopupNode(this).value, AM_Helper.editScript);"
            }, doc);
            popup.insertBefore(menuitem, ins);
 
            menuitem = $C("menuitem", {
                id: "AM-reload-uc",
                hidden: true,
                label: isCN ? "重载 uc 脚本(慎用)" : "Reload uc script",
                style: "font-weight:bold",
                tooltiptext: "仅部分脚本支持。如有问题,重启解决。",
                oncommand: "AM_Helper.getAddon(AM_Helper.getPopupNode(this).value, AM_Helper.reloadUserChromeJS);"
            }, doc);
            popup.insertBefore(menuitem, ins);
 
            menuitem = $C("menuitem", {
                id: "AM-browse-dir",
                label: isCN ? "查看所在目录" : "Browser Dir",
                accesskey: "b",
                oncommand: "AM_Helper.getAddon(AM_Helper.getPopupNode(this).value, AM_Helper.browseDir);"
            }, doc);
            popup.insertBefore(menuitem, ins);
 
            menuitem = $C("menuitem", {
                id: "AM-open-url",
                label: isCN ? "打开安装页面" : "Open Install URL",
                accesskey: "u",
                tooltiptext: null,
                oncommand: "openURL(this.tooltipText)",
            }, doc);
            popup.insertBefore(menuitem, ins);
 
            menuitem = $C("menuitem", {
                id: "AM-copy-name",
                label: isCN ? "复制名称" : "Copy Name",
                accesskey: "c",
                oncommand: "AM_Helper.getAddon(AM_Helper.getPopupNode(this).value, AM_Helper.copyName);"
            }, doc);
            popup.insertBefore(menuitem, ins);
            popup.addEventListener("popupshowing", this, true);
        },
        setItemsAttributes: function(aAddon, event){
            var popup = event.target;
            var doc = popup.ownerDocument;
 
            var
                isExtension = (aAddon.type == "extension"),
                isTheme = (aAddon.type == "theme"),
                isPlugin = (aAddon.type == "plugin"),
                isUserStyle = (aAddon.type == "userstyle"),
                isScriptish = (aAddon.type == "userscript"),
                isGreasemonkey = (aAddon.type == "user-script") || // Greasemonkey
                                (aAddon.type == "greasemonkey-user-script"), // Greasemonkey 1.7+
                isUserScript = isGreasemonkey || isScriptish,
                isUserChromeJS = (aAddon.type == "userchromejs"),
                isService = (aAddon.type == "service"),
                menuitem
            ;
 
            menuitem = doc.getElementById("AM-browse-dir");
            menuitem.hidden = isUserStyle || isUserScript || isService;
 
            menuitem = doc.getElementById("AM-edit-script");
            menuitem.hidden = !isUserChromeJS;
 
            menuitem = doc.getElementById("AM-reload-uc");
            menuitem.hidden = !Config.debug || !isUserChromeJS || !aAddon.enabled;
            if(Config.debug && isUserChromeJS && aAddon.hasError ){
                menuitem.hidden = false;
            }
            var className = isGreasemonkey ? "greasemonkey" : "";
 
            // install url
            menuitem = doc.getElementById("AM-open-url");
            var installURL = isExtension ?
                        (this.getInstallURL(aAddon) || aAddon.homepageURL) :
                        (aAddon.homepageURL || this.getInstallURL(aAddon));
            menuitem.tooltipText = installURL;
            menuitem.hidden = !installURL;
            menuitem.className = installURL ? className : '';
 
            menuitem = doc.getElementById("AM-inspect-addon");
            menuitem.disabled = !("inspectObject" in window);
            menuitem.className = menuitem.disabled ? '' : className;
 
            menuitem = doc.getElementById("AM-copy-name");
            menuitem.tooltipText = aAddon.name;
            menuitem.className = className;
 
        },
 
        getPopupNode: function (aNode) {
            var doc = aNode.ownerDocument;
            return "triggerNode" in aNode.parentNode ? aNode.parentNode.triggerNode : doc.popupNode;
        },
        getAddon: function (aId, aCallback, aEvent) {
            var self = this;
 
            if (this.win.gDetailView._addon) {
                aCallback.apply(this, [this.win.gDetailView._addon, aEvent]);
                return;
            }
 
            (self.platformVersion < 61.0?
                new Promise((resolve, reject) => AddonManager.getAllAddons(addons => resolve(addons))):
                AddonManager.getAllAddons()
            ).then(addons => {
                for (var i = 0; i < addons.length; i++) {
                    if (addons[i].id == aId) {
                        aCallback.apply(self, [addons[i], aEvent]);
                        return;
                    }
                }
            });
        },
 
        inspectAddon: function (aAddon) {
            inspectObject(aAddon);
        },
        inspectUserscript: function (aAddon) {
            inspectObject(aAddon._script);
        },
        browseDir: function (aAddon) {
            switch(aAddon.type){
                case "plugin":
                    var pathes = aAddon.pluginFullpath;
                    for (var i = 0; i < pathes.length; i++) {
                        this.revealPath(pathes[i]);
                    }
                    return;
                case "userchromejs":
                    var file = aAddon._script.file;
                    if(file.exists())
                        file.reveal();
                    return;
            }
 
            // addon
            var gecko = parseInt(Services.appinfo.platformVersion);
            var nsLocalFile = Components.Constructor("@mozilla.org/file/local;1", (gecko >= 14) ? "nsIFile" : "nsILocalFile",
                "initWithPath");
 
            var dir = Services.dirsvc.get("ProfD", Ci.nsIFile);
            dir.append("extensions");
            dir.append(aAddon.id);
            var fileOrDir = dir.path + (dir.exists() ? "" : ".xpi");
            //Application.console.log(fileOrDir);
            try {
                (new nsLocalFile(fileOrDir)).reveal();
            } catch (ex) {
                var addonDir = /.xpi$/.test(fileOrDir) ? dir.parent : dir;
                try {
                    if (addonDir.exists()) {
                        addonDir.launch();
                    }
                } catch (ex) {
                    var uri = Services.io.newFileURI(addonDir);
                    var protSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
                    getService(Ci.nsIExternalProtocolService);
                    protSvc.loadUrl(uri);
                }
            }
        },
        editScript: function(aAddon) {
            if(aAddon.type == "userchromejs"){
                var path = aAddon._script.file.path;
                this.launchEditor(path);
            }
        },
        reloadUserChromeJS: function (aAddon) {
            if(aAddon.type != "userchromejs") return;
 
            var result = confirm("确定要重载吗?\n慎用,仅部分脚本支持,不支持的脚本会出现重复添加按钮或菜单或事件等问题。\n如有问题,重启火狐。");
            if(!result) return;
 
            var script = aAddon._script;
 
            Services.obs.notifyObservers(null, "startupcache-invalidate", "");
            Services.scriptloader.loadSubScript(script.url, {}, script.charset || "utf-8");
        },
        launchEditor: function(path){
                var editor;
                try{
                    editor = Services.prefs.getCharPref("view_source.editor.path","");
                }catch(e){
                }
            if (!editor) {
                var appfile = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
                appfile.initWithPath(path);
                let spWin = window.openDialog("chrome://devtools/content/scratchpad/scratchpad.xul", "Toolkit:Scratchpad", "chrome,resizable=yes,centerscreen,dependent,width=1024,height=600");
                spWin.top.moveTo(0, 0);
                spWin.top.resizeTo(screen.availWidth, screen.availHeight);
                spWin.addEventListener("load", function spWinLoaded() {
                    spWin.removeEventListener("load", spWinLoaded, false);
                    let Scratchpad = spWin.Scratchpad;
                    Scratchpad.setFilename(appfile.path);
                    Scratchpad.addObserver({
                        onReady: function () {
                            Scratchpad.removeObserver(this);
                            Scratchpad.importFromFile.call(Scratchpad, appfile);
                        }
                    });
                }, false);
            } else {
                var UI = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Ci.nsIScriptableUnicodeConverter);
                var platform = window.navigator.platform.toLowerCase();
                UI.charset = platform.indexOf('win') > -1 ? 'GB2312' : 'UTF-8';
                path = UI.ConvertFromUnicode(path);
 
            var appfile = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
            appfile.initWithPath(editor);
            var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
            process.init(appfile);
            process.run(false, [path], 1, {});
            }
        },
        copyName: function (aAddon) {
            this.copyToClipboard(aAddon.name);
        },
 
        getInstallURL: function(aAddon){
            aAddon = aAddon || this.win.gViewController.viewObjects.detail._addon;
            if(!aAddon) return null;
 
            var url = null;
            switch(aAddon.type){
                case "extension":
                case "theme":
                    url = (aAddon.contributionURL || aAddon.reviewURL) || null;
                    return url && url.replace(/\/developers|\/reviews/g, "") || aAddon.creator.url;
                case "greasemonkey-user-script":
                    return aAddon._script._downloadURL || aAddon._script._updateURL;
                case "userscript":
                    url = aAddon._downloadURL || aAddon._updateURL;
                    return url;
                case "userchromejs":
                    return aAddon.homepageURL || aAddon.reviewURL || aAddon.downloadURL || aAddon.updateURL;
                default:
                    return aAddon.homepageURL;
            }
        },
 
        get getPath(){
            var url = this.win.gViewController.viewObjects.detail._addon;
            if(!url) return false;
            return url.pluginFullpath || false;
        },
        setUrlOrPath :function(doc){
            var installURL = this.getInstallURL();
            if (!installURL && !this.getPath) return;
 
            if(!doc.getElementById("detail-InstallURL-row")){
                var value = "",label = "";
                if(this.win.gViewController.currentViewId.indexOf("detail")!= -1){
                    var aAddon = this.win.gViewController.viewObjects.detail._addon;
                    switch (aAddon.type){
                        case "extension":
                        case "theme":
                        case "greasemonkey-user-script":
                            value = installURL;
                            label = "%Installations-Seite%";
                            break;
                        case "plugin":
                            value = this.getPath;
                            label = "%Pfad%";
                            break;
                    }
                }
                if (!!value && !!label) {
                    const row = $C("row", {
                        id:     "detail-InstallURL-row",
                        class:  "detail-row-complex",
                        label:  label,
                    });
                    row.appendChild($C("label", {
                        class:  "detail-row-label",
                        value:  label,
                    }));
                    if (typeof(value) != "string") {
                        const vbox = row.appendChild($C("vbox"));
                        for (var i=0;i< value.length;i++) {
                            vbox.appendChild($C("label", {
                                class:  "detail-row-value text-link",
                                crop:   "end",
                                value:  value[i],
                                href:   value[i],
                                onclick: `
                                    if(event.button == 0) {
                                        AM_Helper.revealPath(this.value);
                                    } else if (event.button == 2){
                                        AM_Helper.copyToClipboard(this.value);
                                    }
                                    return false;`,
                            }));
                        }
                    } else {
                        row.appendChild($C("label", {
                            class:  "detail-row-value text-link",
                            crop:   "end",
                            value:  value,
                            href:   value,
                            onclick: `
                                if(event.button == 2){
                                    AM_Helper.copyToClipboard(this.value);
                                    return false;
                                }`,
                        }));
                    }
                    doc.getElementById("detail-rows").appendChild(row);
                }
            }
        },
        revealPath: function(path){
            var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
            file.initWithPath(path);
            if(file.exists())
                file.reveal();
        },
        copyToClipboard: function (aString) {
            Cc["@mozilla.org/widget/clipboardhelper;1"].
                getService(Ci.nsIClipboardHelper).copyString(aString);
        }
    };
 
    window.userChromeJSAddon = {
        scripts:[],
        unloads: [],
 
        init: function(){
            if ('userchromejs' in AddonManager.addonTypes) return;
 
            this.initScripts();
            this.registerProvider();
            this.addStyle();
        },
        uninit: function(){
            this.unloads.forEach(function(func){ func(); });
        },
        initScripts: function(){
            var scripts = window.userChrome_js.scripts.concat(window.userChrome_js.overlays);
 
            var self = this;
            scripts.forEach(function(script, i){
                self.scripts[i] = new ScriptAddon(script);
            });
        },
        getScriptById: function(aId) {
            for (var i = 0; i < this.scripts.length; i++) {
                if(this.scripts[i].id == aId)
                    return this.scripts[i];
            }
            return null;
        },
        registerProvider: function(){
            var types = null;
            if (AddonManagerPrivate.AddonType) {
                types = [new AddonManagerPrivate.AddonType(
                    "userchromejs",
                    "",
                    isCN ? "脚本" : "userChrome JS",
                    AddonManager.VIEW_TYPE_LIST,
                    9000)];
            }
 
            const provider = {
                getAddonByID: function(aId, aCallback) {
                    let script = userChromeJSAddon.getScriptById(aId);
                    if (aCallback)
                        aCallback(script);
                    else
                        return Promise.resolve(script); // Fx61.0-
                },
 
                getAddonsByTypes: function(aTypes, aCallback) {
                    if (aTypes && aTypes.indexOf("userchromejs") < 0) {
                        if (aCallback)
                            aCallback([]);
                        else
                            return Promise.resolve([]);
                    } else {
                        if (aCallback)
                            aCallback(userChromeJSAddon.scripts);
                        else
                            return Promise.resolve(userChromeJSAddon.scripts);
                    }
                }
            };
 
            AddonManagerPrivate.registerProvider(provider, types);
 
            this.unloads.push(function(){
                AddonManagerPrivate.unregisterProvider(provider);
            });
        },
        addStyle: function(){
            let data = '@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);\
                \
                @-moz-document url("about:addons"), url("chrome://mozapps/content/extensions/extensions.xul") {\
                    #category-userchromejs > .category-icon {\
                        list-style-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAARklEQVQ4jWNgYGD4TyFm+L/uaBJezMDA8H+vgyEGHk4GEIPxGnBhdikKZmBg+P/vEyscjxrASjglEmPAvBMPMPBwMoASDADElRSk+LLlQAAAAABJRU5ErkJggg==);\
                    }\
                }';
            let styleService = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
            let styleURI = Services.io.newURI("data:text/css," + encodeURIComponent(data), null, null);
            styleService.loadAndRegisterSheet(styleURI, Ci.nsIStyleSheetService.USER_SHEET);
 
            this.unloads.push(function(){
                styleService.unregisterSheet(styleURI, Ci.nsIStyleSheetService.USER_SHEET);
            });
        },
    };
    function AddonAuthor(aName, aURL) {
        this.name = aName;
        this.url = aURL;
    }
    AddonAuthor.prototype = {
        name: null,
        url: null,
        // Returns the author's name, defaulting to the empty string
        toString() {
            return this.name || "";
        }
    };
    function ScriptAddon(aScript) {
        this._script = aScript;
 
        this.id = this._script.url;
        this.name = this._script.filename;
        this.description = this._script.description;
        this.enabled = !userChrome_js.scriptDisable[this.name];
 
        // userChrome.js 新增的
        this.version = this._script.version || null;
        this.creator = this._script.author? new AddonAuthor(this._script.author,this._script.namespace):"";
        this.homepageURL = this._script.homepageURL || null;
        this.reviewURL = this._script.reviewURL || null;
        this.reviewCount = 0;
        this.fullDescription = this._script.fullDescription || null;
        this.downloadURL = this._script.downloadURL || null;
        this.optionsURL = this._script.optionsURL || null;
        this.iconURL = this._script.iconURL || iconURL;
        //this.updateDate = new Date(this._script.lastModifiedTime) || null;
        this.hasError = false;
        if(typeof this._script.haserror !="undefined"){
            this.hasError = this._script.haserror;
        }
        if(this.hasError){
            this.enabled = false;
            this.name = this.name + "(脚本运行错误)";
        }
    }
 
    ScriptAddon.prototype = {
        version: null,
        type: "userchromejs",
        isCompatible: true,
        blocklistState: 0,
        appDisabled: false,
        scope: AddonManager.SCOPE_PROFILE,
        name: null,
        creator: null,
        pendingOperations: AddonManager.PENDING_NONE,  // 必须,否则所有都显示 restart
        operationsRequiringRestart: 6,
        // operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_DISABLE,
 
        get optionsURL(){
            if (this.isActive && this._script.optionsURL)
                return this._script.optionsURL;
        },
 
        get isActive() {
            return !this.userDisabled? true: false;
        },
        get userDisabled() {
            return !this.enabled? true: false;
        },
        set userDisabled(val) {
            if (val == this.userDisabled) {
                return val;
            }
 
            AddonManagerPrivate.callAddonListeners(val ? 'onEnabling' : 'onDisabling', this, false);
            var needRunMethod = false;
            if(val){//disabled
                //有 shutdown 方法或者需要重启生效的,直接禁用
                if(this._script.shutdown||this.pendingOperations == AddonManager.PENDING_ENABLE){
                    //非重启生效的,需要运行shutdown方法
                    needRunMethod = this.pendingOperations == AddonManager.PENDING_NONE;
                    this.pendingOperations = AddonManager.PENDING_NONE;
                }else{
                    this.pendingOperations = AddonManager.PENDING_DISABLE;
                }
            }else {
                //有 startup 方法或者需要重启失效的,直接启用
                if(this._script.startup || this.pendingOperations == AddonManager.PENDING_DISABLE){
                    //非重启失效的,需要运行 startup 方法
                    needRunMethod = this.pendingOperations == AddonManager.PENDING_NONE;
                    this.pendingOperations = AddonManager.PENDING_NONE;
                }else{
                    this.pendingOperations = AddonManager.PENDING_ENABLE;
                }
            }
            this.enabled = !val;
            //if (window.userChrome_js && window.userChrome_js.chgScriptStat) {
            //    window.userChrome_js.chgScriptStat(this.name,needRunMethod);
            //}
            if(window.userChromejs){
                userChromejs.chgScriptStat(this.name);
            }
            AddonManagerPrivate.callAddonListeners(val ? 'onEnabled' : 'onDisabled', this);
        },
        get permissions() {
            // var perms = AddonManager.PERM_CAN_UNINSTALL;
            // perms |= this.userDisabled ? AddonManager.PERM_CAN_ENABLE : AddonManager.PERM_CAN_DISABLE;
            var perms;
            if(this.hasError){
                perms = "";
            }else{
                perms = this.userDisabled ? AddonManager.PERM_CAN_ENABLE : AddonManager.PERM_CAN_DISABLE;
            }
            // if (this.updateURL) perms |= AddonManager.PERM_CAN_UPGRADE;
            return perms;
        },
 
        uninstall: function() {
            AddonManagerPrivate.callAddonListeners("onUninstalling", this, false);
            this.needsUninstall = true;
            this.pendingOperations |= AddonManager.PENDING_UNINSTALL;
            AddonManagerPrivate.callAddonListeners("onUninstalled", this);
        },
        cancelUninstall: function() {
            this.needsUninstall = false;
            this.pendingOperations ^= AddonManager.PENDING_UNINSTALL;
            AddonManagerPrivate.callAddonListeners("onOperationCancelled", this);
        },
 
        // Fx62.0-
        enable: function() {
            this.userDisabled = false;
        },
        disable: function() {
            this.userDisabled = true;
        }
    };
 
    AM_Helper.init();
    //延迟初始化,保证其他脚本已加载
    setTimeout(function () {
        if(window.userChrome_js){
            userChromeJSAddon.init();
        }
    },1000);
 
    function $C(name, attr, doc) {
        var el = (doc || document).createXULElement(name);
        if (attr) Object.keys(attr).forEach(function(n){ el.setAttribute(n, attr[n])});
        return el;
    }
})();
cambriancn
小狐狸
小狐狸
  • UID57310
  • 注册日期2019-10-10
  • 最后登录2022-10-05
  • 发帖数28
  • 经验30枚
  • 威望0点
  • 贡献值16点
  • 好评度1点
1楼#
发布于:2020-05-09 12:16
修复不了就算了
lonely_8
非常火狐
非常火狐
  • UID30273
  • 注册日期2009-09-03
  • 最后登录2022-08-09
  • 发帖数733
  • 经验469枚
  • 威望0点
  • 贡献值86点
  • 好评度147点
  • 社区居民
  • 忠实会员
2楼#
发布于:2020-05-09 16:39
扩展页已经大改版,很难改回去了。
cambriancn
小狐狸
小狐狸
  • UID57310
  • 注册日期2019-10-10
  • 最后登录2022-10-05
  • 发帖数28
  • 经验30枚
  • 威望0点
  • 贡献值16点
  • 好评度1点
3楼#
发布于:2020-05-09 17:12
lonely_8:扩展页已经大改版,很难改回去了。回到原帖
好滴,谢谢
lonely_8
非常火狐
非常火狐
  • UID30273
  • 注册日期2009-09-03
  • 最后登录2022-08-09
  • 发帖数733
  • 经验469枚
  • 威望0点
  • 贡献值86点
  • 好评度147点
  • 社区居民
  • 忠实会员
4楼#
发布于:2020-05-09 17:42
// ==UserScript==
// @name         AddonsPage.uc.js
// @description  附件组件页面右键新增查看所在目录,详细信息页面新增安装地址或路径,新增 uc脚本管理页面。
// @author       ywzhaiqi
// @include      main
// @charset      utf-8
// @version      2018.06.27
// @downloadURL  https://raw.github.com/ywzhaiqi/userChromeJS/master/AddonsPage/AddonsPage.uc.js
// @homepageURL  https://github.com/ywzhaiqi/userChromeJS/tree/master/AddonsPage
// @reviewURL    http://bbs.kafan.cn/thread-1617407-1-1.html
// @optionsURL   about:config?filter=view_source.editor.path
// @note         - 附件组件页面右键新增查看所在目录(支持扩展、主题、插件)、复制名字。Greasemonkey、Scriptish 自带已经存在
// @note         - 附件组件详细信息页面新增GM脚本、扩展、主题安装地址和插件路径,右键即复制
// @note         - 新增 uc脚本管理页面
// @note         - 右键菜单 "查看附加组件" 需要 DOM Inspector
// @note         - uc脚本管理界面
// @note         - 启用禁用需要 rebuild_userChrome.uc.xul
// @note         - 编辑命令需要首先设置 view_source.editor.path 的路径
// @note         - 图标请自行添加样式,详细信息见主页
// @note         其它信息见主页
// ==/UserScript==
   
location.href.startsWith('chrome://browser/content/browser.x') && (function(){
   
    var iconURL = "";  // uc Skriptlisten-Symbol
   
    var Config = {
        debug: 1,  // 1 则uc管理界面右键菜单会有 "重载 uc 脚本" 的菜单
        detailView: 1,  // Auf Details-Seite Installation-Link hinzufügen
    };
   
    if(window.AM_Helper){  // Debugging ändern, neu laden ohne neu zu starten
        window.AM_Helper.uninit();
        delete window.AM_Helper;
    }
    if(window.userChromeJSAddon){
        window.userChromeJSAddon.uninit();
        delete window.userChromeJSAddon;
    }
   
    Cu.import("resource://gre/modules/Services.jsm");
    Cu.import("resource://gre/modules/AddonManager.jsm");
   
    let isCN = false;
    try {
        isCN = Services.prefs.getCharPref("general.useragent.locale").indexOf("zh") != -1;
    } catch (e) {
        try {
            isCN = Services.prefs.getCharPref("intl.locale.requested").indexOf("zh") != -1;
        } catch (e) {
            isCN = Services.locale.appLocaleAsBCP47.indexOf("zh") != -1;
        }
    }
   
    var ApplyPatchForScript = (function(){
        const USO_URL_RE = /(^https?:\/\/userscripts.org.*\/scripts\/source\/\d+)\.\w+\.js$/i;
   
        const GFO_URL_RE_1 = /(^https?:\/\/greasyfork.org\/scripts\/code\/\w+)\.\w+\.js$/i;
        const GFO_URL_RE_2 = /(^https?:\/\/greasyfork.org\/scripts\/[^\/]+\/)code[\.\/].*\w+\.js$/i;
   
        // (http://binux.github.io/ThunderLixianExporter/)master/ThunderLixianExporter.user.js
        const GITHUB_URL_RE_1 = /(^https?:\/\/\w+.github.io\/\w+\/)master\/.*.*\w+\.js$/i;
        // 从   https://raw.githubusercontent.com/ywzhaiqi/userscript/master/noNoticetitleflashOnBBS.user.js
        // 转为 https://github.com/ywzhaiqi/userscript/blob/master/noNoticetitleflashOnBBS.user.js
        const GITHUB_URL_RE_2 = /(^https?:\/\/raw.githubusercontent.com\/.*?\/master\/.*\.user\.js$)/i;
   
        function getScriptHomeURL(downURL) {
            var url;
            if (downURL && downURL.startsWith('http')) {
                if (USO_URL_RE.test(downURL)) {
                    url = RegExp.$1.replace(/source/, "show");
                } else if (GFO_URL_RE_1.test(downURL)) {
                    url = RegExp.$1;
                } else if (GFO_URL_RE_2.test(downURL)) {
                    url = RegExp.$1;
                } else if (GITHUB_URL_RE_1.test(downURL)) {
                    url = RegExp.$1;
                } else if (GITHUB_URL_RE_2.test(downURL)) {
                    url = RegExp.$1.replace('raw.githubusercontent.com', 'github.com')
                            .replace('/master/', '/blob/master/');
                }
            }
            return url ? decodeURIComponent(url) : null;
        }
   
        function addHomePage(){
            // 添加 Scriptish 脚本的主页
            if (window.Scriptish_config) {
                Scriptish_config.scripts.forEach(function(script){
                    if(script.homepageURL) return;
   
                    var url = script.updateURL || script.downloadURL;
                    script.homepageURL = getScriptHomeURL(url);
                });
            }
   
            // 添加 Greasemonkey 脚本的主页
            AddonManager.getAddonsByTypes(['greasemonkey-user-script'], function (aAddons) {
                aAddons.forEach(function (aAddon) {
                    if (aAddon.homepageURL) return;
   
                    var url = aAddon._script._downloadURL || aAddon._script._updateURL;
                    var homepageURL = getScriptHomeURL(url);
                    if (homepageURL) {
                        aAddon.homepageURL = homepageURL;
                    } else {
                        // console.log(aAddon.name, url);
                    }
                });
            });
        }
   
        return {
            init: addHomePage
        }
    })();
   
    setTimeout(function(){
        ApplyPatchForScript.init();
    }, 2000);
   
    window.AM_Helper = {
        init: function(){
            document.addEventListener("DOMContentLoaded", this, false);
            this.platformVersion = parseFloat(Services.appinfo.platformVersion);
        },
        uninit: function(){
            document.removeEventListener("DOMContentLoaded", this, false);
        },
        handleEvent: function(event){
            switch(event.type){
                case "DOMContentLoaded":
                    var doc = event.target;
                    var win = doc.defaultView;
   
                    if (["about:addons","chrome://mozapps/content/extensions/extensions.xul"].indexOf(doc.URL) == -1)
                        return;
   
                    this.addPopupMenu(doc);
   
                    // 给菜单调用
                    win.AM_Helper = AM_Helper;
                    this.win = win;
   
                    if (Config.detailView) {
                        var self = this;
                        var observer = new MutationObserver(function(e) {
                            e = e[e.length-1];
                            if(e.attributeName == "loading") {
                                var doc = e.target.ownerDocument;
                                self.setUrlOrPath(doc);
                            }
                        });
                        observer.observe(doc.getElementById("detail-view"), {attributes: true});
                    }
                    break;
                case "popupshowing":
                    if(this.win.document.popupNode){
                        this.getAddon(this.win.document.popupNode.value,
                            this.setItemsAttributes,
                            event);
                    }
                    break;
            }
        },
        addPopupMenu: function(doc){
            var ins = doc.getElementById("menuitem_uninstallItem");
            if(!ins) return;
   
            ins = ins.nextSibling;
            var popup = ins.parentNode;
   
            var menuitem = $C("menuseparator", {
                id: "AM-separator-1"
            }, doc);
            popup.insertBefore(menuitem, ins);
   
            menuitem = $C("menuitem", {
                id: "AM-inspect-addon",
                label: isCN ? "查看附加组件" : "Inspect Addon",
                accesskey: "i",
                tooltipText: isCN ? "调用 DOM Inspector 查看 addon 对象" : "Addon mit Dom Inspector inspizieren",
                oncommand: "AM_Helper.getAddon(AM_Helper.getPopupNode(this).value, AM_Helper.inspectAddon);"
            }, doc);
            popup.insertBefore(menuitem, ins);
   
            menuitem = $C("menuitem", {
                id: "AM-edit-script",
                label: isCN ? "编辑" : "Edit",
                accesskey: "e",
                hidden: true,
                oncommand: "AM_Helper.getAddon(AM_Helper.getPopupNode(this).value, AM_Helper.editScript);"
            }, doc);
            popup.insertBefore(menuitem, ins);
   
            menuitem = $C("menuitem", {
                id: "AM-reload-uc",
                hidden: true,
                label: isCN ? "重载 uc 脚本(慎用)" : "Reload uc script",
                style: "font-weight:bold",
                tooltiptext: "仅部分脚本支持。如有问题,重启解决。",
                oncommand: "AM_Helper.getAddon(AM_Helper.getPopupNode(this).value, AM_Helper.reloadUserChromeJS);"
            }, doc);
            popup.insertBefore(menuitem, ins);
   
            menuitem = $C("menuitem", {
                id: "AM-browse-dir",
                label: isCN ? "查看所在目录" : "Browser Dir",
                accesskey: "b",
                oncommand: "AM_Helper.getAddon(AM_Helper.getPopupNode(this).value, AM_Helper.browseDir);"
            }, doc);
            popup.insertBefore(menuitem, ins);
   
            menuitem = $C("menuitem", {
                id: "AM-open-url",
                label: isCN ? "打开安装页面" : "Open Install URL",
                accesskey: "u",
                tooltiptext: null,
                oncommand: "openURL(this.tooltipText)",
            }, doc);
            popup.insertBefore(menuitem, ins);
   
            menuitem = $C("menuitem", {
                id: "AM-copy-name",
                label: isCN ? "复制名称" : "Copy Name",
                accesskey: "c",
                oncommand: "AM_Helper.getAddon(AM_Helper.getPopupNode(this).value, AM_Helper.copyName);"
            }, doc);
            popup.insertBefore(menuitem, ins);
            popup.addEventListener("popupshowing", this, true);
        },
        setItemsAttributes: function(aAddon, event){
            var popup = event.target;
            var doc = popup.ownerDocument;
   
            var
                isExtension = (aAddon.type == "extension"),
                isTheme = (aAddon.type == "theme"),
                isPlugin = (aAddon.type == "plugin"),
                isUserStyle = (aAddon.type == "userstyle"),
                isScriptish = (aAddon.type == "userscript"),
                isGreasemonkey = (aAddon.type == "user-script") || // Greasemonkey
                                (aAddon.type == "greasemonkey-user-script"), // Greasemonkey 1.7+
                isUserScript = isGreasemonkey || isScriptish,
                isUserChromeJS = (aAddon.type == "userchromejs"),
                isService = (aAddon.type == "service"),
                menuitem
            ;
   
            menuitem = doc.getElementById("AM-browse-dir");
            menuitem.hidden = isUserStyle || isUserScript || isService;
   
            menuitem = doc.getElementById("AM-edit-script");
            menuitem.hidden = !isUserChromeJS;
   
            menuitem = doc.getElementById("AM-reload-uc");
            menuitem.hidden = !Config.debug || !isUserChromeJS || !aAddon.enabled;
            if(Config.debug && isUserChromeJS && aAddon.hasError ){
                menuitem.hidden = false;
            }
            var className = isGreasemonkey ? "greasemonkey" : "";
   
            // install url
            menuitem = doc.getElementById("AM-open-url");
            var installURL = isExtension ?
                        (this.getInstallURL(aAddon) || aAddon.homepageURL) :
                        (aAddon.homepageURL || this.getInstallURL(aAddon));
            menuitem.tooltipText = installURL;
            menuitem.hidden = !installURL;
            menuitem.className = installURL ? className : '';
   
            menuitem = doc.getElementById("AM-inspect-addon");
            menuitem.disabled = !("inspectObject" in window);
            menuitem.className = menuitem.disabled ? '' : className;
   
            menuitem = doc.getElementById("AM-copy-name");
            menuitem.tooltipText = aAddon.name;
            menuitem.className = className;
   
        },
   
        getPopupNode: function (aNode) {
            var doc = aNode.ownerDocument;
            return "triggerNode" in aNode.parentNode ? aNode.parentNode.triggerNode : doc.popupNode;
        },
        getAddon: function (aId, aCallback, aEvent) {
            var self = this;
   
            if (this.win.gDetailView._addon) {
                aCallback.apply(this, [this.win.gDetailView._addon, aEvent]);
                return;
            }
   
            (self.platformVersion < 61.0?
                new Promise((resolve, reject) => AddonManager.getAllAddons(addons => resolve(addons))):
                AddonManager.getAllAddons()
            ).then(addons => {
                for (var i = 0; i < addons.length; i++) {
                    if (addons[i].id == aId) {
                        aCallback.apply(self, [addons[i], aEvent]);
                        return;
                    }
                }
            });
        },
   
        inspectAddon: function (aAddon) {
            inspectObject(aAddon);
        },
        inspectUserscript: function (aAddon) {
            inspectObject(aAddon._script);
        },
        browseDir: function (aAddon) {
            switch(aAddon.type){
                case "plugin":
                    var pathes = aAddon.pluginFullpath;
                    for (var i = 0; i < pathes.length; i++) {
                        this.revealPath(pathes[i]);
                    }
                    return;
                case "userchromejs":
                    var file = aAddon._script.file;
                    if(file.exists())
                        file.reveal();
                    return;
            }
   
            // addon
            var gecko = parseInt(Services.appinfo.platformVersion);
            var nsLocalFile = Components.Constructor("@mozilla.org/file/local;1", (gecko >= 14) ? "nsIFile" : "nsILocalFile",
                "initWithPath");
   
            var dir = Services.dirsvc.get("ProfD", Ci.nsIFile);
            dir.append("extensions");
            dir.append(aAddon.id);
            var fileOrDir = dir.path + (dir.exists() ? "" : ".xpi");
            //Application.console.log(fileOrDir);
            try {
                (new nsLocalFile(fileOrDir)).reveal();
            } catch (ex) {
                var addonDir = /.xpi$/.test(fileOrDir) ? dir.parent : dir;
                try {
                    if (addonDir.exists()) {
                        addonDir.launch();
                    }
                } catch (ex) {
                    var uri = Services.io.newFileURI(addonDir);
                    var protSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
                    getService(Ci.nsIExternalProtocolService);
                    protSvc.loadUrl(uri);
                }
            }
        },
        editScript: function(aAddon) {
            if(aAddon.type == "userchromejs"){
                var path = aAddon._script.file.path;
                this.launchEditor(path);
            }
        },
        reloadUserChromeJS: function (aAddon) {
            if(aAddon.type != "userchromejs") return;
   
            var result = confirm("确定要重载吗?\n慎用,仅部分脚本支持,不支持的脚本会出现重复添加按钮或菜单或事件等问题。\n如有问题,重启火狐。");
            if(!result) return;
   
            var script = aAddon._script;
   
            Services.obs.notifyObservers(null, "startupcache-invalidate", "");
            Services.scriptloader.loadSubScript(script.url, {}, script.charset || "utf-8");
        },
        launchEditor: function(path){
                var editor;
                try{
                    editor = Services.prefs.getCharPref("view_source.editor.path","");
                }catch(e){
                }
            if (!editor) {
                var appfile = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
                appfile.initWithPath(path);
                let spWin = window.openDialog("chrome://devtools/content/scratchpad/scratchpad.xul", "Toolkit:Scratchpad", "chrome,resizable=yes,centerscreen,dependent,width=1024,height=600");
                spWin.top.moveTo(0, 0);
                spWin.top.resizeTo(screen.availWidth, screen.availHeight);
                spWin.addEventListener("load", function spWinLoaded() {
                    spWin.removeEventListener("load", spWinLoaded, false);
                    let Scratchpad = spWin.Scratchpad;
                    Scratchpad.setFilename(appfile.path);
                    Scratchpad.addObserver({
                        onReady: function () {
                            Scratchpad.removeObserver(this);
                            Scratchpad.importFromFile.call(Scratchpad, appfile);
                        }
                    });
                }, false);
            } else {
                var UI = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Ci.nsIScriptableUnicodeConverter);
                var platform = window.navigator.platform.toLowerCase();
                UI.charset = platform.indexOf('win') > -1 ? 'GB2312' : 'UTF-8';
                path = UI.ConvertFromUnicode(path);
   
            var appfile = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
            appfile.initWithPath(editor);
            var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
            process.init(appfile);
            process.run(false, [path], 1, {});
            }
        },
        copyName: function (aAddon) {
            this.copyToClipboard(aAddon.name);
        },
   
        getInstallURL: function(aAddon){
            aAddon = aAddon || this.win.gViewController.viewObjects.detail._addon;
            if(!aAddon) return null;
   
            var url = null;
            switch(aAddon.type){
                case "extension":
                case "theme":
                    url = (aAddon.contributionURL || aAddon.reviewURL) || null;
                    return url && url.replace(/\/developers|\/reviews/g, "") || aAddon.creator.url;
                case "greasemonkey-user-script":
                    return aAddon._script._downloadURL || aAddon._script._updateURL;
                case "userscript":
                    url = aAddon._downloadURL || aAddon._updateURL;
                    return url;
                case "userchromejs":
                    return aAddon.homepageURL || aAddon.reviewURL || aAddon.downloadURL || aAddon.updateURL;
                default:
                    return aAddon.homepageURL;
            }
        },
   
        get getPath(){
            var url = this.win.gViewController.viewObjects.detail._addon;
            if(!url) return false;
            return url.pluginFullpath || false;
        },
        setUrlOrPath :function(doc){
            var installURL = this.getInstallURL();
            if (!installURL && !this.getPath) return;
   
            if(!doc.getElementById("detail-InstallURL-row")){
                var value = "",label = "";
                if(this.win.gViewController.currentViewId.indexOf("detail")!= -1){
                    var aAddon = this.win.gViewController.viewObjects.detail._addon;
                    switch (aAddon.type){
                        case "extension":
                        case "theme":
                        case "greasemonkey-user-script":
                            value = installURL;
                            label = "%Installations-Seite%";
                            break;
                        case "plugin":
                            value = this.getPath;
                            label = "%Pfad%";
                            break;
                    }
                }
                if (!!value && !!label) {
                    const row = $C("row", {
                        id:     "detail-InstallURL-row",
                        class:  "detail-row-complex",
                        label:  label,
                    });
                    row.appendChild($C("label", {
                        class:  "detail-row-label",
                        value:  label,
                    }));
                    if (typeof(value) != "string") {
                        const vbox = row.appendChild($C("vbox"));
                        for (var i=0;i< value.length;i++) {
                            vbox.appendChild($C("label", {
                                class:  "detail-row-value text-link",
                                crop:   "end",
                                value:  value[i],
                                href:   value[i],
                                onclick: `
                                    if(event.button == 0) {
                                        AM_Helper.revealPath(this.value);
                                    } else if (event.button == 2){
                                        AM_Helper.copyToClipboard(this.value);
                                    }
                                    return false;`,
                            }));
                        }
                    } else {
                        row.appendChild($C("label", {
                            class:  "detail-row-value text-link",
                            crop:   "end",
                            value:  value,
                            href:   value,
                            onclick: `
                                if(event.button == 2){
                                    AM_Helper.copyToClipboard(this.value);
                                    return false;
                                }`,
                        }));
                    }
                    doc.getElementById("detail-rows").appendChild(row);
                }
            }
        },
        revealPath: function(path){
            var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
            file.initWithPath(path);
            if(file.exists())
                file.reveal();
        },
        copyToClipboard: function (aString) {
            Cc["@mozilla.org/widget/clipboardhelper;1"].
                getService(Ci.nsIClipboardHelper).copyString(aString);
        }
    };
   
    window.userChromeJSAddon = {
        scripts:[],
        unloads: [],
   
        init: function(){
            if ('userchromejs' in AddonManager.addonTypes) return;
   
            this.initScripts();
            document.addEventListener('DOMContentLoaded', (event) => {
                if(event.target.location.href != 'chrome://mozapps/content/extensions/aboutaddons.html') return;
                const doc = event.target;
                this.addCategoryButton(doc);
                const main = doc.getElementById('main');
                if(main){
                    const observer = new doc.defaultView.MutationObserver((m) => {
                        if(!doc.querySelector('addon-list[type="userchromejs"]'))
                            return;
                        doc.querySelector('.header-name').textContent = isCN ? "管理您的脚本" : "Manage Yors userChromeJSs";
                        for(const addonCard of doc.querySelectorAll('addon-card')){
                            this.addToggleButton(doc, addonCard);
                        }
                    });
                    observer.observe(main, {childList: true});
                }
            }, false);
            this.registerProvider();
            this.addStyle();
        },
        addCategoryButton: function(doc) {
            const pcb = doc.querySelector('button.category[name="plugin"]');
            if(!pcb) return;
            doc.defaultView.setTimeout(() => {
                const isSelected = !doc.querySelector('button.category[aria-selected="true"]');
                const scb = pcb.cloneNode(true);
                scb.setAttribute('viewid', 'addons://list/userchromejs');
                scb.setAttribute('name', 'userchromejs');
                scb.toggleAttribute('selected', isSelected);
                scb.setAttribute('aria-selected', isSelected);
                scb.firstElementChild.removeAttribute('data-l10n-id');
                scb.firstElementChild.textContent = isCN ? "脚本" : "userChrome JS";
                pcb.after(scb);
                if(isSelected){
                    pcb.click();
                    doc.defaultView.setTimeout(() => {
                        scb.click();
                    }, 0);
                }
 
            }, 0);
        },
        addToggleButton: function (doc, addonCard) {
            if(addonCard.querySelector('panel-item[action="toggle-disabled"]'))
                return;
            const moreBtn = addonCard.querySelector('.more-options-button');
            if(!moreBtn) return;
            const toggleButton = doc.createElement('input');
            toggleButton.type = 'checkbox';
            toggleButton.className = 'toggle-button extension-enable-button';
            toggleButton.setAttribute('action', 'toggle-disabled');
            moreBtn.before(toggleButton);
            const _update = addonCard.update;
            if(typeof _update === 'function'){
                const updateToggleButton = function () {
                    if(this.addon && this.addon.type === 'userchromejs'){
                        const toggleButton = this.card.querySelector('input.toggle-button');
                        toggleButton.checked = !this.addon.userDisabled;
                        const toggleDisabledAction = toggleButton.checked ? 'enable' : 'disable';
                        this.card.ownerDocument.l10n.setAttributes(
                            toggleButton,
                            `${toggleDisabledAction}-addon-button-label`
                        );
                    }
                }
                addonCard.update = function (...args) {
                    const rt = _update.apply(this, args);
                    updateToggleButton.call(this);
                    return rt;
                }
                updateToggleButton.call(addonCard);
            }
        },
        uninit: function(){
            this.unloads.forEach(function(func){ func(); });
        },
        initScripts: function(){
            var scripts = window.userChrome_js.scripts.concat(window.userChrome_js.overlays);
   
            var self = this;
            scripts.forEach(function(script, i){
                self.scripts[i] = new ScriptAddon(script);
            });
        },
        getScriptById: function(aId) {
            for (var i = 0; i < this.scripts.length; i++) {
                if(this.scripts[i].id == aId)
                    return this.scripts[i];
            }
            return null;
        },
        registerProvider: function(){
            var types = null;
            if (AddonManagerPrivate.AddonType) {
                types = [new AddonManagerPrivate.AddonType(
                    "userchromejs",
                    "",
                    isCN ? "脚本" : "userChrome JS",
                    AddonManager.VIEW_TYPE_LIST,
                    9000)];
            }
   
            const provider = {
                getAddonByID: function(aId, aCallback) {
                    let script = userChromeJSAddon.getScriptById(aId);
                    if (aCallback)
                        aCallback(script);
                    else
                        return Promise.resolve(script); // Fx61.0-
                },
   
                getAddonsByTypes: function(aTypes, aCallback) {
                    if (aTypes && aTypes.indexOf("userchromejs") < 0) {
                        if (aCallback)
                            aCallback([]);
                        else
                            return Promise.resolve([]);
                    } else {
                        if (aCallback)
                            aCallback(userChromeJSAddon.scripts);
                        else
                            return Promise.resolve(userChromeJSAddon.scripts);
                    }
                }
            };
   
            AddonManagerPrivate.registerProvider(provider, types);
   
            this.unloads.push(function(){
                AddonManagerPrivate.unregisterProvider(provider);
            });
        },
        addStyle: function(){
            let data = '\
                @-moz-document url("about:addons"), url("chrome://mozapps/content/extensions/extensions.xul"), url("chrome://mozapps/content/extensions/aboutaddons.html") {\
                    .category[name="userchromejs"] {\
                        background-image: url(chrome://devtools/skin/images/tool-styleeditor.svg);\
                    }\
                    #category-userchromejs > .category-icon {\
                        list-style-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAARklEQVQ4jWNgYGD4TyFm+L/uaBJezMDA8H+vgyEGHk4GEIPxGnBhdikKZmBg+P/vEyscjxrASjglEmPAvBMPMPBwMoASDADElRSk+LLlQAAAAABJRU5ErkJggg==);\
                    }\
                }';
            let styleService = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
            let styleURI = Services.io.newURI("data:text/css," + encodeURIComponent(data), null, null);
            styleService.loadAndRegisterSheet(styleURI, Ci.nsIStyleSheetService.USER_SHEET);
   
            this.unloads.push(function(){
                styleService.unregisterSheet(styleURI, Ci.nsIStyleSheetService.USER_SHEET);
            });
        },
    };
    function AddonAuthor(aName, aURL) {
        this.name = aName;
        this.url = aURL;
    }
    AddonAuthor.prototype = {
        name: null,
        url: null,
        // Returns the author's name, defaulting to the empty string
        toString() {
            return this.name || "";
        }
    };
    function ScriptAddon(aScript) {
        this._script = aScript;
   
        this.id = this._script.filename;
        this.name = this._script.filename;
        this.description = this._script.description;
        this.enabled = !userChrome_js.scriptDisable[this.name];
   
        // userChrome.js 新增的
        this.version = this._script.version || null;
        this.creator = this._script.author? new AddonAuthor(this._script.author,this._script.namespace):"";
        this.homepageURL = this._script.homepageURL || null;
        this.reviewURL = this._script.reviewURL || null;
        this.reviewCount = 0;
        this.fullDescription = this._script.fullDescription || null;
        this.downloadURL = this._script.downloadURL || null;
        this.optionsURL = this._script.optionsURL || null;
        this.iconURL = this._script.iconURL || iconURL;
        //this.updateDate = new Date(this._script.lastModifiedTime) || null;
        this.hasError = false;
        if(typeof this._script.haserror !="undefined"){
            this.hasError = this._script.haserror;
        }
        if(this.hasError){
            this.enabled = false;
            this.name = this.name + "(脚本运行错误)";
        }
    }
   
    ScriptAddon.prototype = {
        version: null,
        type: "userchromejs",
        isCompatible: true,
        blocklistState: 0,
        appDisabled: false,
        scope: AddonManager.SCOPE_PROFILE,
        name: null,
        creator: null,
        pendingOperations: AddonManager.PENDING_NONE,  // 必须,否则所有都显示 restart
        operationsRequiringRestart: 6,
        // operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_DISABLE,
   
        get optionsURL(){
            if (this.isActive && this._script.optionsURL)
                return this._script.optionsURL;
        },
   
        get isActive() {
            return !this.userDisabled? true: false;
        },
        get userDisabled() {
            return !this.enabled? true: false;
        },
        set userDisabled(val) {
            if (val == this.userDisabled) {
                return val;
            }
   
            AddonManagerPrivate.callAddonListeners(val ? 'onEnabling' : 'onDisabling', this, false);
            var needRunMethod = false;
            if(val){//disabled
                //有 shutdown 方法或者需要重启生效的,直接禁用
                if(this._script.shutdown||this.pendingOperations == AddonManager.PENDING_ENABLE){
                    //非重启生效的,需要运行shutdown方法
                    needRunMethod = this.pendingOperations == AddonManager.PENDING_NONE;
                    this.pendingOperations = AddonManager.PENDING_NONE;
                }else{
                    this.pendingOperations = AddonManager.PENDING_DISABLE;
                }
            }else {
                //有 startup 方法或者需要重启失效的,直接启用
                if(this._script.startup || this.pendingOperations == AddonManager.PENDING_DISABLE){
                    //非重启失效的,需要运行 startup 方法
                    needRunMethod = this.pendingOperations == AddonManager.PENDING_NONE;
                    this.pendingOperations = AddonManager.PENDING_NONE;
                }else{
                    this.pendingOperations = AddonManager.PENDING_ENABLE;
                }
            }
            this.enabled = !val;
            //if (window.userChrome_js && window.userChrome_js.chgScriptStat) {
            //    window.userChrome_js.chgScriptStat(this.name,needRunMethod);
            //}
            if(window.userChromejs){
                userChromejs.chgScriptStat(this.name);
            }
            AddonManagerPrivate.callAddonListeners(val ? 'onEnabled' : 'onDisabled', this);
        },
        get permissions() {
            // var perms = AddonManager.PERM_CAN_UNINSTALL;
            // perms |= this.userDisabled ? AddonManager.PERM_CAN_ENABLE : AddonManager.PERM_CAN_DISABLE;
            var perms;
            if(this.hasError){
                perms = "";
            }else{
                perms = this.userDisabled ? AddonManager.PERM_CAN_ENABLE : AddonManager.PERM_CAN_DISABLE;
            }
            // if (this.updateURL) perms |= AddonManager.PERM_CAN_UPGRADE;
            return perms;
        },
   
        uninstall: function() {
            AddonManagerPrivate.callAddonListeners("onUninstalling", this, false);
            this.needsUninstall = true;
            this.pendingOperations |= AddonManager.PENDING_UNINSTALL;
            AddonManagerPrivate.callAddonListeners("onUninstalled", this);
        },
        cancelUninstall: function() {
            this.needsUninstall = false;
            this.pendingOperations ^= AddonManager.PENDING_UNINSTALL;
            AddonManagerPrivate.callAddonListeners("onOperationCancelled", this);
        },
   
        // Fx62.0-
        enable: function() {
            this.userDisabled = false;
        },
        disable: function() {
            this.userDisabled = true;
        }
    };
   
    AM_Helper.init();
    //延迟初始化,保证其他脚本已加载
    setTimeout(function () {
        if(window.userChrome_js){
            userChromeJSAddon.init();
        }
    },1000);
   
    function $C(name, attr, doc) {
        var el = (doc || document).createXULElement(name);
        if (attr) Object.keys(attr).forEach(function(n){ el.setAttribute(n, attr[n])});
        return el;
    }
})();



显示 uc 脚本勉强能救活,至于脚本前面的能(右键菜单?)就没办法了,新版扩展页无右键功能。
cambriancn
小狐狸
小狐狸
  • UID57310
  • 注册日期2019-10-10
  • 最后登录2022-10-05
  • 发帖数28
  • 经验30枚
  • 威望0点
  • 贡献值16点
  • 好评度1点
5楼#
发布于:2020-05-09 21:16
aunsen
小狐狸
小狐狸
  • UID34416
  • 注册日期2010-11-03
  • 最后登录2024-03-27
  • 发帖数56
  • 经验63枚
  • 威望0点
  • 贡献值32点
  • 好评度4点
  • 社区居民
  • 忠实会员
6楼#
发布于:2020-05-10 14:38
lonely_8:// ==UserScript==
// @name         AddonsPage.uc.js
// @description  附件组件页面右键新增查看所在目录,详细信息页面新增安装地址或路径,新增 uc脚本管理页面。
//...
回到原帖
大神能帮忙修复一下BMMultiColumn脚本吗?其他都还好,就这个多栏书签离不了,或者有什么更好的方法,CSS能做到自适应吗



https://www.firefox.net.cn/read-121616
游客

返回顶部