tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Browser.sys.mjs (3436B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 const lazy = {};
      6 
      7 ChromeUtils.defineESModuleGetters(lazy, {
      8  pprint: "chrome://remote/content/shared/Format.sys.mjs",
      9  waitForObserverTopic: "chrome://remote/content/marionette/sync.sys.mjs",
     10 });
     11 
     12 /**
     13 * Quits the application with the provided flags.
     14 *
     15 * Optional {@link nsIAppStartup} flags may be provided as
     16 * an array of masks, and these will be combined by ORing
     17 * them with a bitmask. The available masks are defined in
     18 * https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIAppStartup.
     19 *
     20 * Crucially, only one of the *Quit flags can be specified. The |eRestart|
     21 * flag may be bit-wise combined with one of the *Quit flags to cause
     22 * the application to restart after it quits.
     23 *
     24 * @param {Array.<string>=} flags
     25 *     Constant name of masks to pass to |Services.startup.quit|.
     26 *     If empty or undefined, |nsIAppStartup.eAttemptQuit| is used.
     27 * @param {boolean=} safeMode
     28 *     Optional flag to indicate that the application has to
     29 *     be restarted in safe mode.
     30 * @param {boolean=} isWindowless
     31 *     Optional flag to indicate that the browser was started in windowless mode.
     32 *
     33 * @returns {Record<string, boolean>}
     34 *     Dictionary containing information that explains the shutdown reason.
     35 *     The value for `cause` contains the shutdown kind like "shutdown" or
     36 *     "restart", while `forced` will indicate if it was a normal or forced
     37 *     shutdown of the application. "in_app" is always set to indicate that
     38 *     it is a shutdown triggered from within the application.
     39 */
     40 export async function quit(flags = [], safeMode = false, isWindowless = false) {
     41  if (flags.includes("eSilently")) {
     42    if (!isWindowless) {
     43      throw new Error(
     44        `Silent restarts only allowed with "moz:windowless" capability set`
     45      );
     46    }
     47    if (!flags.includes("eRestart")) {
     48      throw new TypeError(`"silently" only works with restart flag`);
     49    }
     50  }
     51 
     52  const quits = ["eConsiderQuit", "eAttemptQuit", "eForceQuit"];
     53 
     54  let quitSeen;
     55  let mode = 0;
     56  if (flags.length) {
     57    for (let k of flags) {
     58      if (!(k in Ci.nsIAppStartup)) {
     59        throw new TypeError(lazy.pprint`Expected ${k} in ${Ci.nsIAppStartup}`);
     60      }
     61 
     62      if (quits.includes(k)) {
     63        if (quitSeen) {
     64          throw new TypeError(`${k} cannot be combined with ${quitSeen}`);
     65        }
     66        quitSeen = k;
     67      }
     68 
     69      mode |= Ci.nsIAppStartup[k];
     70    }
     71  }
     72 
     73  if (!quitSeen) {
     74    mode |= Ci.nsIAppStartup.eAttemptQuit;
     75  }
     76 
     77  // Notify all windows that an application quit has been requested.
     78  const cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(
     79    Ci.nsISupportsPRBool
     80  );
     81  Services.obs.notifyObservers(cancelQuit, "quit-application-requested");
     82 
     83  // If the shutdown of the application is prevented force quit it instead.
     84  if (cancelQuit.data) {
     85    mode |= Ci.nsIAppStartup.eForceQuit;
     86  }
     87 
     88  // Delay response until the application is about to quit.
     89  const quitApplication = lazy.waitForObserverTopic("quit-application");
     90 
     91  if (safeMode) {
     92    Services.startup.restartInSafeMode(mode);
     93  } else {
     94    Services.startup.quit(mode);
     95  }
     96 
     97  return {
     98    cause: (await quitApplication).data,
     99    forced: cancelQuit.data,
    100    in_app: true,
    101  };
    102 }