升级 Firefox 后 userChromeJS 脚本用不了的问题处理记录

Firefox 2022-07-13 194℃ 0 0

推荐优先寻找大佬的代码参考,找不到参考时优先考虑使用 copilot /tabnine 自动生成
然后就是 searchfox.org 搜索(用不了的)的方法名,一般会有注释说用什么方法替代,或者方法的调用参数修改为什么

createElement创建菜单异常.png

这是 7X 版本的变动了,Copilot 生成的代码通常会出现这种 BUG
创建按钮/创建菜单导致界面显示异常/菜单无法弹出
createElement创建菜单异常.pngcreateElement创建菜单异常.png

document.createElement修改为document.createXULElement

无法修改某个菜单

一般的 menupopup 菜单,通常都是你的代码执行的时候该菜单还没生成,比如搜索框右键菜单,是在右键点击搜索框的时候才初始化的,相关示例代码如下

let { node } = CustomizableUI.getWidget('searchbar')?.forWindow(window);
function addAccessKey(e) {
   node.removeEventListener('click', addAccessKey);
   var timer = setInterval(() => {
     clearInterval(timer);
     e.ownerDocument.querySelector('.searchbar-paste-and-search').setAttribute('accesskey', 'S');
   }, 10);
}
node.addEventListener('click', addAccessKey, false);

如果是汉堡菜单,参考下面的代码,在汉堡菜单第一次展示的时候操作(因为汉堡菜单只有在第一次点击三道杠的时候初始化)

PanelUI.mainView.addEventListener("ViewShowing", function(event) {
  // 在这里操作即可
}, { once: true });

无法获取选中文本

content.getSelection()或者document.commandDispatcher.focusedWindow.getSelection()无法获取选中文本,应该是 E10s启用开始就获取不了,可以使用sendMessage或者使用别的 api 替代。我找到了这个 api

// ==UserScript==
// @name           selectionDemo.uc.js
// @namespace      https://github.com/benzBrake/FirefoxCustomize/
// @author         Ryan
// @startup        window.selectionDemo.init();
// @shutdown       window.selectionDemo.destroy();
// ==/UserScript==
(function () {
    window.selectionDemo = {
        init: function () {
            gBrowser.tabpanels.addEventListener("mouseup", this, false);
        },
        destroy: function () {
            gBrowser.tabpanels.removeEventListener("mouseup", this, false);
        },
        handleEvent: function (event) {
            switch (event.type) {
                case 'mouseup':
                    // 鼠标按键释放时读取选中文本
                    try {
                        gBrowser.selectedBrowser.finder.getInitialSelection().then((r) => {
                            this._selectedTXT = r.selectedText;
                        })
                    } catch (e) { }
                    break;
            }
        },
        get text() {
            return this._selectedTXT || "";
        }
    }
})();

调用selectionDemo.text即可获取选中文本

getURLSpecFromFile 函数不存在

Firefox 92 废止 api,主要是调用第三方编辑器或者读取某个文件的时候要用到,添加这个函数

function getURLSpecFromFile(aFile) {
    var aURL;
    if (typeof userChrome !== "undefined" && typeof userChrome.getURLSpecFromFile !== "undefined") {
        aURL = userChrome.getURLSpecFromFile(aFile);
    } else if (this.appVersion < 92) {
        aURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromFile(aFile);
    } else {
        aURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromActualFile(aFile);
    }
    return aURL;
}

然后调用getURLSpecFromFile(aFile)即可

Services.search.getDefault() 获取的搜索引擎对象不能用

因为改成了异步api,使用方法如下

// 这两个方法参考 vue
function isDef(v) {
    return v !== undefined && v !== null
}

function isPromise(val) {
    return (
        isDef(val) &&
        typeof val.then === 'function' &&
        typeof val.catch === 'function'
    )
}
let engine = Services.search.getDefault();
if (isPromise(engine)) {
   engine.then(s => {
      console.log(s._name);
   });
} else {
  console.log(engine._name);
}

OS is not defined

对于这种对象不存在的首先确认模块被删掉了还是 Firefox 启动的时候不再载入。

比如我是 Firefox Nightly 2022.07.13 遇到这个问题的,找个老版本,比如 Firefox 100,在浏览器内容工具箱(Ctrl+Alt+Shift+I)的控制台输入新版不存在的对象名。

浏览器内容工具箱-查看对象.jpg浏览器内容工具箱-查看对象.jpg

点击跳转按钮,然后复制源地址

复制源地址.jpg复制源地址.jpg

比如我这复制出来的源地址是resource://gre/modules/osfile/osfile_async_front.jsm

在新版本 Firefox 的浏览器内容工具箱的控制台导入试试

Components.utils.import("resource://gre/modules/osfile/osfile_async_front.jsm")

在新版本Firefox测试导入模块.jpg在新版本Firefox测试导入模块.jpg

如果像上面这样可以导入,那你在脚本开始加入这一行代导入一下即可

Components.utils.import("resource://gre/modules/osfile/osfile_async_front.jsm")

如果不行,寻找替代或者等待有缘人更新

openUILinkIn 报错

这个方法从 Firefox 78 开始修改了调用参数
Firefox 78 以前

openUILinkIn(uri.spec, where, false, postData || null);

Firefox 78 以后

openUILinkIn(uri.spec, where, {
    postData: postData || null,
    triggeringPrincipal: where === 'current' ?
        gBrowser.selectedBrowser.contentPrincipal : (
            /^(f|ht)tps?:/.test(uri.spec) ?
                Services.scriptSecurityManager.createNullPrincipal({}) :
                Services.scriptSecurityManager.getSystemPrincipal()
        )
});

评论 (0)

Top