Source code

Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at */
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
pprint: "chrome://remote/content/shared/Format.sys.mjs",
waitForObserverTopic: "chrome://remote/content/marionette/sync.sys.mjs",
* Quits the application with the provided flags.
* Optional {@link nsIAppStartup} flags may be provided as
* an array of masks, and these will be combined by ORing
* them with a bitmask. The available masks are defined in
* Crucially, only one of the *Quit flags can be specified. The |eRestart|
* flag may be bit-wise combined with one of the *Quit flags to cause
* the application to restart after it quits.
* @param {Array.<string>=} flags
* Constant name of masks to pass to |Services.startup.quit|.
* If empty or undefined, |nsIAppStartup.eAttemptQuit| is used.
* @param {boolean=} safeMode
* Optional flag to indicate that the application has to
* be restarted in safe mode.
* @param {boolean=} isWindowless
* Optional flag to indicate that the browser was started in windowless mode.
* @returns {Object<string,boolean>}
* Dictionary containing information that explains the shutdown reason.
* The value for `cause` contains the shutdown kind like "shutdown" or
* "restart", while `forced` will indicate if it was a normal or forced
* shutdown of the application. "in_app" is always set to indicate that
* it is a shutdown triggered from within the application.
export async function quit(flags = [], safeMode = false, isWindowless = false) {
if (flags.includes("eSilently")) {
if (!isWindowless) {
throw new Error(
`Silent restarts only allowed with "moz:windowless" capability set`
if (!flags.includes("eRestart")) {
throw new TypeError(`"silently" only works with restart flag`);
const quits = ["eConsiderQuit", "eAttemptQuit", "eForceQuit"];
let quitSeen;
let mode = 0;
if (flags.length) {
for (let k of flags) {
if (!(k in Ci.nsIAppStartup)) {
throw new TypeError(lazy.pprint`Expected ${k} in ${Ci.nsIAppStartup}`);
if (quits.includes(k)) {
if (quitSeen) {
throw new TypeError(`${k} cannot be combined with ${quitSeen}`);
quitSeen = k;
mode |= Ci.nsIAppStartup[k];
if (!quitSeen) {
mode |= Ci.nsIAppStartup.eAttemptQuit;
// Notify all windows that an application quit has been requested.
const cancelQuit = Cc[";1"].createInstance(
Services.obs.notifyObservers(cancelQuit, "quit-application-requested");
// If the shutdown of the application is prevented force quit it instead.
if ( {
mode |= Ci.nsIAppStartup.eForceQuit;
// Delay response until the application is about to quit.
const quitApplication = lazy.waitForObserverTopic("quit-application");
if (safeMode) {
} else {
return {
cause: (await quitApplication).data,
in_app: true,