tor-browser

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

DefaultBrowserCheck.sys.mjs (7527B)


      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
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
      6 
      7 let lazy = {};
      8 ChromeUtils.defineESModuleGetters(lazy, {
      9  BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs",
     10  CommonDialog: "resource://gre/modules/CommonDialog.sys.mjs",
     11  SessionStartup: "resource:///modules/sessionstore/SessionStartup.sys.mjs",
     12 });
     13 
     14 export var DefaultBrowserCheck = {
     15  async prompt(win) {
     16    const shellService = win.getShellService();
     17    const needPin =
     18      (await shellService.doesAppNeedPin()) ||
     19      (await shellService.doesAppNeedStartMenuPin());
     20 
     21    win.MozXULElement.insertFTLIfNeeded("branding/brand.ftl");
     22    win.MozXULElement.insertFTLIfNeeded(
     23      "browser/defaultBrowserNotification.ftl"
     24    );
     25    // Record default prompt impression
     26    let now = Math.floor(Date.now() / 1000).toString();
     27    Services.prefs.setCharPref(
     28      "browser.shell.mostRecentDefaultPromptSeen",
     29      now
     30    );
     31 
     32    // Resolve the translations for the prompt elements and return only the
     33    // string values
     34 
     35    let pinMessage;
     36    if (AppConstants.platform == "macosx") {
     37      pinMessage = "default-browser-prompt-message-pin-mac";
     38    } else if (
     39      AppConstants.platform == "win" &&
     40      Services.sysinfo.getProperty("hasWinPackageId", false)
     41    ) {
     42      pinMessage = "default-browser-prompt-message-pin-msix";
     43    } else {
     44      pinMessage = "default-browser-prompt-message-pin";
     45    }
     46    let [promptTitle, promptMessage, askLabel, yesButton, notNowButton] = (
     47      await win.document.l10n.formatMessages([
     48        {
     49          id: needPin
     50            ? "default-browser-prompt-title-pin"
     51            : "default-browser-prompt-title-alt",
     52        },
     53        {
     54          id: needPin ? pinMessage : "default-browser-prompt-message-alt",
     55        },
     56        { id: "default-browser-prompt-checkbox-not-again-label" },
     57        {
     58          id: needPin
     59            ? "default-browser-prompt-button-primary-set"
     60            : "default-browser-prompt-button-primary-alt",
     61        },
     62        { id: "default-browser-prompt-button-secondary" },
     63      ])
     64    ).map(({ value }) => value);
     65 
     66    let ps = Services.prompt;
     67    let buttonFlags =
     68      ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_0 +
     69      ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_1 +
     70      ps.BUTTON_POS_0_DEFAULT;
     71    let rv = await ps.asyncConfirmEx(
     72      win.browsingContext,
     73      ps.MODAL_TYPE_INTERNAL_WINDOW,
     74      promptTitle,
     75      promptMessage,
     76      buttonFlags,
     77      yesButton,
     78      notNowButton,
     79      null,
     80      askLabel,
     81      false, // checkbox state
     82      {
     83        headerIconCSSValue: lazy.CommonDialog.DEFAULT_APP_ICON_CSS,
     84      }
     85    );
     86    let buttonNumClicked = rv.get("buttonNumClicked");
     87    let checkboxState = rv.get("checked");
     88    if (buttonNumClicked == 0) {
     89      // We must explicitly await pinning to the taskbar before
     90      // trying to set as default. If we fall back to setting
     91      // as default through the Windows Settings menu that interferes
     92      // with showing the pinning notification as we no longer have
     93      // window focus.
     94      try {
     95        await shellService.pinToTaskbar();
     96      } catch (e) {
     97        this.log.error("Failed to pin to taskbar", e);
     98      }
     99      try {
    100        await shellService.pinToStartMenu();
    101      } catch (e) {
    102        this.log.error("Failed to pin to Start Menu", e);
    103      }
    104      try {
    105        await shellService.setAsDefault();
    106      } catch (e) {
    107        this.log.error("Failed to set the default browser", e);
    108      }
    109    }
    110    if (checkboxState) {
    111      shellService.shouldCheckDefaultBrowser = false;
    112      Services.prefs.setCharPref("browser.shell.userDisabledDefaultCheck", now);
    113    }
    114 
    115    try {
    116      let resultEnum = buttonNumClicked * 2 + !checkboxState;
    117      Glean.browser.setDefaultResult.accumulateSingleSample(resultEnum);
    118    } catch (ex) {
    119      /* Don't break if Telemetry is acting up. */
    120    }
    121  },
    122 
    123  /**
    124   * Checks if the default browser check prompt will be shown.
    125   *
    126   * @param {boolean} isStartupCheck
    127   *   If true, prefs will be set and telemetry will be recorded.
    128   * @returns {boolean} True if the default browser check prompt will be shown.
    129   */
    130  async willCheckDefaultBrowser(isStartupCheck) {
    131    let win = lazy.BrowserWindowTracker.getTopWindow({
    132      allowFromInactiveWorkspace: true,
    133    });
    134    let shellService = win.getShellService();
    135 
    136    // Perform default browser checking.
    137    if (!shellService) {
    138      return false;
    139    }
    140 
    141    let shouldCheck =
    142      !AppConstants.DEBUG && shellService.shouldCheckDefaultBrowser;
    143 
    144    // Even if we shouldn't check the default browser, we still continue when
    145    // isStartupCheck = true to set prefs and telemetry.
    146    if (!shouldCheck && !isStartupCheck) {
    147      return false;
    148    }
    149 
    150    // Skip the "Set Default Browser" check during first-run or after the
    151    // browser has been run a few times.
    152    const skipDefaultBrowserCheck =
    153      Services.prefs.getBoolPref(
    154        "browser.shell.skipDefaultBrowserCheckOnFirstRun"
    155      ) &&
    156      !Services.prefs.getBoolPref(
    157        "browser.shell.didSkipDefaultBrowserCheckOnFirstRun"
    158      );
    159 
    160    let promptCount = Services.prefs.getIntPref(
    161      "browser.shell.defaultBrowserCheckCount",
    162      0
    163    );
    164 
    165    // If SessionStartup's state is not initialized, checking sessionType will set
    166    // its internal state to "do not restore".
    167    await lazy.SessionStartup.onceInitialized;
    168    let willRecoverSession =
    169      lazy.SessionStartup.sessionType == lazy.SessionStartup.RECOVER_SESSION;
    170 
    171    // Don't show the prompt if we're already the default browser.
    172    let isDefault = false;
    173    let isDefaultError = false;
    174    try {
    175      isDefault = shellService.isDefaultBrowser(isStartupCheck, false);
    176    } catch (ex) {
    177      isDefaultError = true;
    178    }
    179 
    180    if (isDefault && isStartupCheck) {
    181      let now = Math.floor(Date.now() / 1000).toString();
    182      Services.prefs.setCharPref(
    183        "browser.shell.mostRecentDateSetAsDefault",
    184        now
    185      );
    186    }
    187 
    188    let willPrompt = shouldCheck && !isDefault && !willRecoverSession;
    189 
    190    if (willPrompt) {
    191      if (skipDefaultBrowserCheck) {
    192        if (isStartupCheck) {
    193          Services.prefs.setBoolPref(
    194            "browser.shell.didSkipDefaultBrowserCheckOnFirstRun",
    195            true
    196          );
    197        }
    198        willPrompt = false;
    199      } else {
    200        promptCount++;
    201        if (isStartupCheck) {
    202          Services.prefs.setIntPref(
    203            "browser.shell.defaultBrowserCheckCount",
    204            promptCount
    205          );
    206        }
    207        if (!AppConstants.RELEASE_OR_BETA && promptCount > 3) {
    208          willPrompt = false;
    209        }
    210      }
    211    }
    212 
    213    if (isStartupCheck) {
    214      try {
    215        // Report default browser status on startup to telemetry
    216        // so we can track whether we are the default.
    217        Glean.browser.isUserDefault[isDefault ? "true" : "false"].add();
    218        Glean.browser.isUserDefaultError[
    219          isDefaultError ? "true" : "false"
    220        ].add();
    221        Glean.browser.setDefaultAlwaysCheck[
    222          shouldCheck ? "true" : "false"
    223        ].add();
    224        Glean.browser.setDefaultDialogPromptRawcount.accumulateSingleSample(
    225          promptCount
    226        );
    227      } catch (ex) {
    228        /* Don't break the default prompt if telemetry is broken. */
    229      }
    230    }
    231 
    232    return willPrompt;
    233  },
    234 };