欢迎来到gary的位于博客园的(没太多技术含量的)博客

2020年代仍有Firefox userChrome JS脚本(介绍、简略教程、资源)

直到现在(2022年中更新时)Firefox的 userChrome script(简称uc脚本) 仍然可以使用。我们无法知道在遥远的或不久的将来Mozilla会不会让uc脚本完全失效,这两年已有人在说,但自57以后,是uc脚本让一些人(例如我)不需要(或暂时不需要)放弃Firefox转用其他浏览器。目前看来,uc脚本仍然可以让我们这些普通用户安心使用下去。

本人的技术重点不在于浏览器,只是个浏览器用户。本文非专业性很强的文章

背景

2017年Firefox的“量子”版本(57)发布,中止了所有旧扩展(Addon/Extension,又称附加组件,与“插件 Plugins 不同)的支持。XUL、XPCOM、XBL等旧的被称为Legacy的技术被宣称要废弃。57开始只支持webExtension的扩展。

这一改变我相信使得很多人离开Firefox,因为可自订性、可玩性降低很多(例如主界面不能再随意更改、扩展不能再任意操作浏览器about:config内的项目),一大堆的旧扩展作废。

但旧技术也没有完全被剥离,仍然有人通过 userChrome script(简称uc脚本) 的方式实现一些webExtension无法实现(或暂时无法实现)的功能。甚至有人通过uc脚本复活了好多个Legacy扩展的100%功能。可以说只要uc脚本仍可用,以前的Firefox玩法都可以继续。

在本来就小众的Firefox用户群中,uc脚本更加小众,本篇将介绍一些资源和笔者自己写的uc脚本,还有简略的脚本编写教程(默认你会js)(我这个教程写得不算好,但目前没发现有大神在写)。

userChrome JS脚本与userChrome.css有关但不同,脚本是JavaScript的,不是CSS

如何启用uc脚本

Firefox每更新一个版本,启用uc脚本的方法就很可能会变化。以下这些常跟进Firefox的变化提供启用方法的:

方法一般就是将一些用于启用的js、xml、css文件放入Firefox程序目录及profile中,然后就可以把你的具体.uc.js文件放入对应位置使用。

以上所列这些启用方式,每一套也称为一种uc脚本管理器。

除了启用uc脚本的方法会变化,uc脚本代码也需要根据Firefox版本的更新而修改。如果常更新是较麻烦的,因此我自己使用半年更新一次的Firefox ESR。

编写uc脚本的简略教程

启用浏览器工具箱

编写uc脚本需要使用浏览器工具箱(Browser Tools)来调试。可以让你用鼠标选择和可查看浏览器主界面上的任意一部位的部件(导航栏、地址栏、标签栏等),也可以让你输入执行整个浏览器级别的js代码。

浏览器工具箱(Browser Tools)开启的快捷键是Ctrl+Shift+Alt+I

注意与网页开发所用的工具箱Ctrl+Shift+I不同,我们需要的这个是可以调试整个浏览器的,而那个只调试一个tab内的网页

而Firefox默认是禁用了Browser Tools的。启用的方法为:

  • 先打开一个tab页面的开发者工具(Ctrl+Shift+I

  • 右上角三个点->设置

  • 勾选高级设置下面的以下两个

    • Enable browser chrome and add-on debugging toolboxes

    • Enable remote debugging

现在可以关闭网页开发工具,打开浏览器工具箱了。打开时会弹窗确认允许远程调试连接。

编写代码

学了WebExtension的而未学Firefox Legacy技术的可以看看这篇比较文章

这里不详细讲,也不会去教js,默认读者有一些js基础了。只简略说些常见的做法,具体还请参考下面的参考资源,本篇中的许多具体脚本的链接也可以作为例子学习。

uc脚本的代码有可能因Firefox版本更新而需要改变

主界面上的部件、按钮等都是有DOM节点的,一般都有id和class,可以像平常使用js一样对它们做一些操作。请在浏览器工具箱中慢慢研究。

.uc.js特别的头部

打开一个.uc.js一般常看到

// ==UserScript==
// @name            <script name>
// @author          <someone>
// @include         main
// @onlyonce
// ==/UserScript==

这些//开头的,虽然对于JS来说是没有用的注释,但对于uc脚本来说,在一个.uc.js文件被执行前,是会先寻找并解析这种@开头的关键字的(这也可能因你所用uc脚本管理器而异)。

@include指定你的这个.uc.js文件在怎么样的Firefox窗口中执行。Firefox是可以打开多窗口的(包括那些下载对话框之类的,也算一种窗口)。经常,我们只需要脚本在Firefox的主(可以打开多个)窗口执行,所以使用@include main排除下载、关于等非主窗口。

@onlyonce指定该uc.js在整个Firefox中只被执行一遍(而不是每打开一个窗口就执行一次)。例如添加自定义widget(即工具栏按钮)的代码在整个Firefox只应该被执行一遍,它就会在每个浏览器窗口中出现该widget,这时就需要@onlyonce

注意,以xiaoxialflood的uc脚本启动管理器为例,是否使用@onlyonce,影响这个uc.js文件被加载执行时的global对象(需要看这个页面中描述的targetObj参数才能表述清楚)。

Standard code modules

操作DOM节点还不够,有些Firefox内置的功能最好调用一些内部Standard code modules来使用。例如常看到

const xxx = Components.utils.import("resource://xxx/xxx.jsm");
const xxx = Components.classes["@mozilla.org/xxx/xxx;1"].getService(Components.xxx.xxx);

这些Standard code modules具体是通过.jsm文件(Firefox源码中,也是JS)封装的。

根据Mozilla此文 ,使用ChromeUtils.import好过Components.utils.import

XUL namespace

uc中常需用到XUL这个namespace。关于namespace,这里有介绍,常见的namespace有

注意这些URL不是给我们打开访问的,只是形式(一种假网址)

HTML: http://www.w3.org/1999/xhtml
XULhttp://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul
XBL: http://www.mozilla.org/xbl

脚本中可用document.createElementNS来创建XUL namespace的元素,也可以用简化的document.createXULElement来直接创建浏览器UI常用的XUL。

css内也会出现如

@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");

管理好每个.uc.js文件的命名空间

编写uc脚本时,将js变量和对象名称限制在命名空间内是个好习惯,例如在一个.uc.js文件内:

console.log("xxx.uc.js");
(() => {
    你的代码
})();

除了上面方式,也可以创建一个有名称的Object来当你的命名空间。

一些资源

我自己写的uc脚本

因我自己使用半年更新一次的Firefox ESR,我写的这些脚本也只会为ESR更新。

  1. Tabs at bottom

    把标签栏放在FIrefox窗口底部最下方。不是地址栏下方,而是网页内容下方,整个窗口最下方

    虽然少,但这个帖子说明了仍有人有这个需求:现在还有没有标签栏可以下置的浏览器? - 知乎。因此也希望各个浏览器能考虑将其添加为原生选项。

  2. about:config menu

    如果你要经常更改about:config里的某一个值,那么打开修改挺麻烦的。可以这个快捷菜单。把你自己经常要改的加进去

  3. Right click tab close

    右键单击标签栏上的标签按钮来关闭标签。如果想调出标签按钮菜单,按住shift再右击。

    这个也可以配合一个仅在活动标签显示关闭按钮的css使用

  4. Sidebar Switch

    快速地通过点击Firefox窗口左侧(最大化时就是屏幕左侧)边缘来开关侧边栏。

    以前的Legacy扩展All in One Sidebar(AiOS)已废弃,但Firefox官方加入了原生的侧边栏,只是没有通过边缘快速开关的功能。用这个简单的uc脚本实现了AiOS基本一样的体验。

  5. firefoxtaskmonitor

    在每个标签按钮上用柱条显示该标签页占用的CPU及内存。在标签栏最右边,显示其他任务(扩展等)的CPU及内存。

  6. newtab-btn-menu

    你可以右键点击新建标签的加号按钮,然后选择新建标签打开剪贴板中的网址

更多我的脚本和代码在 https://garywill.github.io/

如何使Firefox保持安装临时扩展

在没有我们这里的方法之前,Firefox不支持终端中用CLI命令加载扩展,只允许安装经过Mozilla签名的(上AMO去提交并签名再下载回来。可以不发布)。在about:debugging页面中可以用点击“加载临时扩展”以安装未打包、未签名的扩展,但关闭Firefox后不会维持,要重新操作一遍。

这里,我在about:debugging页面中用F12查看了加载临时按钮的元素信息后,简单地在Searchfox搜索了Firefox的源代码内容,便得到了方法。

通过uc脚本代码,可以使Firefox每次启动时自动加载临时扩展:

var FileUtils = Cu.import("resource://gre/modules/FileUtils.jsm").FileUtils 
var nsifile = new FileUtils.File("未打包的扩展路径,目录下应有manifest.json");
Cu.import("resource://gre/modules/AddonManager.jsm");
AddonManager.installTemporaryAddon(nsifile);

其他人的uc脚本或Legacy技术资源

如何使用旧的XUL/XPCOM Firefox legacy扩展

Mozilla官方已经删掉了所有XUL/XPCOM旧技术创建的扩展,ca-archive收集了它们。可以找旧的Firefox 52 esr或56来安装ca-archive,然后便可以在浏览器内浏览、下载、安装legacy扩展。

甚至,xiaoxiaoflood/firefox-scripts提供通过uc脚本使legacy扩展能够在新(57以后)的Firefox运行的可能。

文档或其他参考资源

posted @ 2020-01-19 20:46  garywill  阅读(2363)  评论(0编辑  收藏  举报
gary的位于博客园的博客