后台任务模式

Gecko 支持在特殊的无头“后台任务”模式下运行特权 JavaScript。后台任务模式旨在用于定期维护任务。第一个使用者将是检查更新,即使 Firefox 未运行。

对后台任务模式的支持受构建标志 MOZ_BACKGROUNDTASKS 控制。

添加新的后台任务

后台任务通过 --backgroundtask TASKNAME 调用。任务必须在构建时打包;后台任务运行时按以下位置(按顺序)查找常规 JSM 模块

  1. (应用程序特定) resource:///modules/backgroundtasks/BackgroundTask_TASKNAME.sys.mjs

  2. (工具包/通用) resource://gre/modules//backgroundtasks/BackgroundTask_TASKNAME.sys.mjs

要添加新的后台任务,请在您的 moz.build 文件中添加类似以下内容的代码段

EXTRA_JS_MODULES.backgroundtasks += [
    "BackgroundTask_TASKNAME.sys.mjs",
]

实现后台任务

BackgroundTask_TASKNAME.sys.mjs 中,定义一个返回 Promise 的函数 runBackgroundTaskrunBackgroundTask 将被等待,它解析到的整数值将用作 --backgroundtask TASKNAME 调用的退出代码。可选地,runBackgroundTask 可以将 nsICommandLine 实例 作为参数。例如

export async function runBackgroundTask(commandLine) {
    return Number.parseInt(commandLine.getArgument(0), 10);
}

当像 --backgroundtask TASKNAME EXITCODE 这样调用时,此任务将简单地以命令行上给出的退出代码完成。

任务模块可以选择导出一个名为 backgroundTaskTimeoutSec 的整数值,该值将控制任务在超时之前可以运行多长时间。如果未指定值,则将使用 pref toolkit.backgroundtasks.defaultTimeoutSec 中存储的超时值。

特殊退出代码

退出代码 2-4 具有特殊含义

  • 退出代码 2 (EXIT_CODE.NOT_FOUND) 表示未找到或无法加载具有给定 TASKNAME 的后台任务。

  • 退出代码 3 (EXIT_CODE.EXCEPTION) 表示后台任务调用因异常而被拒绝。

  • 退出代码 4 (EXIT_CODE.TIMEOUT) 表示后台任务在完成之前超时。

有关详细信息,请参阅 EXIT_CODE

仅测试的后台任务

对仅测试的后台任务有特殊支持。在您的 moz.build 文件中添加类似以下内容的代码段

TESTING_JS_MODULES.backgroundtasks += [
    "BackgroundTask_TESTONLYTASKNAME.sys.mjs",
]

有关更多详细信息,请参阅 XPCSHELL_TESTING_MODULES_URI

调试后台任务

后台任务模式支持使用 JavaScript 调试器以及 Firefox Devtools 和浏览器工具箱。当使用命令行参数 --jsdebugger(以及可选的 --wait-for-jsdebugger)调用时,后台任务框架将启动浏览器工具箱,连接到后台任务,并在任务实现的第一行暂停执行。浏览器工具箱使用临时配置文件启动(与后台任务本身创建的临时配置文件处于同一级别)。浏览器工具箱配置文件的偏好设置从默认浏览配置文件复制,允许配置 devtools 偏好设置。(--start-debugger-server 命令行选项也已识别;有关详细信息,请参阅 firefox --backgroundtask success --attach-console --help 的输出。)

调用后台任务

使用 BackgroundTasksRunner::RunInDetachedProcess 是一个帮助程序,用于在 Gecko 中打开一个新的后台进程。它自动管理配置 1)让新进程比启动进程存活更久,以及 2)正确转义参数。该函数可以在非主进程中安全调用。

现有的后台任务

  • BackgroundTask_removeDirectory

    删除给定名称的子目录和/或具有给定后缀的子目录,所有这些都在给定的父目录中。建议通过相应的辅助函数 BackgroundTasksRunner::RemoveDirectoryInDetachedProcess 运行它。

    测试可以使用 toolkit.background_tasks.remove_directory.testing.sleep_ms 来查看长期任务是否可以在启动进程关闭后完成工作。

  • BackgroundTask_defaultagent

    在 Windows 上报告系统默认值的遥测数据。有关更多信息,请参阅 默认浏览器代理

后台任务模式运行时环境

大多数后台任务在临时配置文件中运行

后台任务旨在用于定期维护任务,尤其是全局/每个安装的维护任务。为了允许后台任务与常规的带头浏览会话同时运行,默认情况下,它们使用临时配置文件运行。此临时配置文件在后台任务主进程退出时被删除。每个后台任务都会应用 backgroundtasks/defaults/backgroundtasks.js 中的偏好设置,但任何其他偏好设置配置都必须由各个任务处理。随着时间的推移,我们预计一个小的后台任务功能库将不断发展,以使其更容易锁定和读取默认浏览配置文件中的特定首选项,声明每个安装的首选项等。

可以在非临时(即持久)配置文件中运行后台任务。有关详细信息,请参阅 Bug 1775132

后台任务默认限制 XPCOM 实例图

使后台任务“轻量级”的技术机制非常简单。XPCOM 为通过观察者服务松散耦合组件声明了许多观察者通知。其中一些观察者通知被声明为类别通知,允许使用者在静态 components.conf 注册文件中(或现在已弃用的 chrome.manifest 文件中)注册自己。在后台任务模式下,默认情况下不会注册类别通知。

特别是对于 Firefox,这意味着 BrowserContentHandler.sys.mjs 未注册为命令行处理程序。这意味着 BrowserGlue.sys.mjs 未加载,这会使常规带头浏览启动中断。

有关如何更改此默认行为,请参阅 定义静态组件的文档,并参阅 Bug 1675848 以了解实现的详细信息。

大多数后台任务不处理更新

为了防止后台任务和 Firefox 运行时生命周期之间出现意外交互,例如 Bug 1736373 中发现的那些交互,大多数后台任务不处理应用程序更新。启动进程在 ::ShouldProcessUpdates 中决定是否处理更新,并且确定特定后台任务是否处理更新的谓词是 BackgroundTasks::IsUpdatingTaskName

在关闭时启动(且未更新)的后台任务不会阻止 Firefox 更新。但是,这可能导致 Firefox 在正在运行的后台任务下进行更新:请参阅 此问题的摘要。通常,后台任务应该尽可能精简和短暂,并且在启动后不太可能启动其他子进程,因此它们不应该遇到此问题,但仍然有可能。请参阅下图,该图显示了进程的生命周期。

甘特图 标题 Firefox 关闭时启动的后台任务 日期格式 YYYY-MM-DD 轴格式 部分 Firefox firefox (版本 N) :2014-01-03, 3d 更新程序 :2014-01-06, 1d firefox (版本 N+1) :2014-01-07, 3d firefox --backgroundtask ... (版本 N) :2014-01-05, 3d

大多数后台任务会生成控制台输出

后台任务通常在输出对用户不可见的情况下被调度:由 Windows 任务计划程序、在关闭时等。因此,始终生成控制台输出通常是安全的。但某些任务,尤其是开发人员构建期间执行的关闭任务,即使在 Firefox 主进程退出后,也可能“污染”控制台。为了避免这种情况,后台任务可以选择不产生输出;确定特定后台任务是否产生输出的谓词是 BackgroundTasks::IsNoOutputTaskName。可以通过提供 --attach-console 命令行标志或将 MOZ_BACKGROUNDTASKS_IGNORE_NO_OUTPUT 环境变量设置为非空值来覆盖此谓词。

pingsender 后台任务选择不产生输出:请参见 Bug 1736623

更多细节

最大和最小运行时间

后台任务旨在在(非常)短时间内完成其工作。有两个首选项全局控制这些值

toolkit.backgroundtasks.defaultTimeoutSec(默认 10 分钟)

定义最大运行时间。一旦超过此超时时间,将启动关闭序列,而不管仍在运行的 JS 负载的状态如何。因此建议,任何可能长时间运行的 JS 负载添加异步关闭阻止程序,使其退出或在适当的位置检查 isInOrBeyondShutdownPhase,否则可能会发生关闭挂起。

toolkit.backgroundtasks.defaultMinTaskRuntimeMS(默认 500 毫秒)

设置即使是空后台任务在启动其关闭序列之前也将等待的最小运行时间。主要目的是在要求组件关闭之前,为任何异步运行的启动组件启动提供足够的时间来完成其启动。请注意,这是从负载开始的挂钟计时,因此如果后台任务本身花费更长时间,则不会向执行添加额外时间。如果后台任务本身可能会导致进一步的异步组件启动或其他处理,则应注意在返回之前等待它们完成。请注意,在实际启动任务之前 还有额外的 100 毫秒延迟,加上进程启动和关闭开销,因此即使是空任务也至少需要 ~800 毫秒才能完成(在现代 Windows 笔记本电脑上)toolkit.backgroundtasks.defaultMinTaskRuntimeMS == 500

覆盖全局首选项值

此外,您可以通过以下方式控制每个任务的这些值

export const backgroundTaskTimeoutSec = <some seconds>;
export const backgroundTaskMinRuntimeMS = <some millisecs>;

此处任务定义的顶部