mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 02:09:05 +02:00 
			
		
		
		
	Now any number of experiments can use the glean feature to enable/disable metrics in their experiment! Differential Revision: https://phabricator.services.mozilla.com/D246793
		
			
				
	
	
		
			498 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			498 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* 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 http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
 | 
						|
 | 
						|
let lazy = {};
 | 
						|
ChromeUtils.defineESModuleGetters(lazy, {
 | 
						|
  BrowserInitState: "resource:///modules/BrowserGlue.sys.mjs",
 | 
						|
  BrowserUsageTelemetry: "resource:///modules/BrowserUsageTelemetry.sys.mjs",
 | 
						|
  FormAutofillUtils: "resource://gre/modules/shared/FormAutofillUtils.sys.mjs",
 | 
						|
  LoginHelper: "resource://gre/modules/LoginHelper.sys.mjs",
 | 
						|
  NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
 | 
						|
  OsEnvironment: "resource://gre/modules/OsEnvironment.sys.mjs",
 | 
						|
  PlacesDBUtils: "resource://gre/modules/PlacesDBUtils.sys.mjs",
 | 
						|
  ShellService: "resource:///modules/ShellService.sys.mjs",
 | 
						|
  TelemetryReportingPolicy:
 | 
						|
    "resource://gre/modules/TelemetryReportingPolicy.sys.mjs",
 | 
						|
  UsageReporting: "resource://gre/modules/UsageReporting.sys.mjs",
 | 
						|
});
 | 
						|
 | 
						|
/**
 | 
						|
 * Used to collect various bits of telemetry during browser startup.
 | 
						|
 *
 | 
						|
 */
 | 
						|
export let StartupTelemetry = {
 | 
						|
  // Some tasks are expensive because they involve significant disk IO, and
 | 
						|
  // may also write information to disk. If we submit the telemetry that may
 | 
						|
  // happen anyway, but if we don't then this is undesirable, so those tasks are
 | 
						|
  // only run if we will submit the results.
 | 
						|
  // Why run any telemetry code at all if we don't submit the data? Because
 | 
						|
  // local and autoland builds usually do not submit telemetry, but we still
 | 
						|
  // want to be able to run automated tests to check the code _worked_.
 | 
						|
  get _willUseExpensiveTelemetry() {
 | 
						|
    return (
 | 
						|
      AppConstants.MOZ_TELEMETRY_REPORTING &&
 | 
						|
      Services.prefs.getBoolPref(
 | 
						|
        "datareporting.healthreport.uploadEnabled",
 | 
						|
        false
 | 
						|
      )
 | 
						|
    );
 | 
						|
  },
 | 
						|
 | 
						|
  _runIdleTasks(tasks, profilerMarker) {
 | 
						|
    for (let task of tasks) {
 | 
						|
      ChromeUtils.idleDispatch(async () => {
 | 
						|
        if (!Services.startup.shuttingDown) {
 | 
						|
          let startTime = Cu.now();
 | 
						|
          try {
 | 
						|
            await task();
 | 
						|
          } catch (ex) {
 | 
						|
            console.error(ex);
 | 
						|
          } finally {
 | 
						|
            ChromeUtils.addProfilerMarker(
 | 
						|
              profilerMarker,
 | 
						|
              startTime,
 | 
						|
              task.toSource()
 | 
						|
            );
 | 
						|
          }
 | 
						|
        }
 | 
						|
      });
 | 
						|
    }
 | 
						|
  },
 | 
						|
 | 
						|
  browserIdleStartup() {
 | 
						|
    let tasks = [
 | 
						|
      // FOG doesn't need to be initialized _too_ early because it has a pre-init buffer.
 | 
						|
      () => this.initFOG(),
 | 
						|
 | 
						|
      () => this.contentBlocking(),
 | 
						|
      () => this.dataSanitization(),
 | 
						|
      () => this.pipEnabled(),
 | 
						|
      () => this.sslKeylogFile(),
 | 
						|
      () => this.osAuthEnabled(),
 | 
						|
      () => this.startupConditions(),
 | 
						|
      () => this.httpsOnlyState(),
 | 
						|
      () => this.globalPrivacyControl(),
 | 
						|
    ];
 | 
						|
    if (this._willUseExpensiveTelemetry) {
 | 
						|
      tasks.push(() => lazy.PlacesDBUtils.telemetry());
 | 
						|
    }
 | 
						|
    if (AppConstants.platform == "win") {
 | 
						|
      tasks.push(
 | 
						|
        () => this.pinningStatus(),
 | 
						|
        () => this.isDefaultHandler()
 | 
						|
      );
 | 
						|
    } else if (AppConstants.platform == "macosx") {
 | 
						|
      tasks.push(() => this.macDockStatus());
 | 
						|
    }
 | 
						|
 | 
						|
    this._runIdleTasks(tasks, "startupTelemetryIdleTask");
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Use this function as an entry point to collect telemetry that we hope
 | 
						|
   * to collect once per session, at any arbitrary point in time, and
 | 
						|
   *
 | 
						|
   * **which we are okay with sometimes not running at all.**
 | 
						|
   *
 | 
						|
   * See BrowserGlue.sys.mjs's _scheduleBestEffortUserIdleTasks for more
 | 
						|
   * details.
 | 
						|
   */
 | 
						|
  bestEffortIdleStartup() {
 | 
						|
    let tasks = [
 | 
						|
      () => this.primaryPasswordEnabled(),
 | 
						|
      () => this.trustObjectCount(),
 | 
						|
      () => lazy.OsEnvironment.reportAllowedAppSources(),
 | 
						|
    ];
 | 
						|
    if (AppConstants.platform == "win" && this._willUseExpensiveTelemetry) {
 | 
						|
      tasks.push(
 | 
						|
        () => lazy.BrowserUsageTelemetry.reportProfileCount(),
 | 
						|
        () => lazy.BrowserUsageTelemetry.reportInstallationTelemetry()
 | 
						|
      );
 | 
						|
    }
 | 
						|
    this._runIdleTasks(tasks, "startupTelemetryLateIdleTask");
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Initialize Firefox-on-Glean.
 | 
						|
   *
 | 
						|
   * This is at the top because it's a bit different from the other code here
 | 
						|
   * which is strictly collecting specific metrics.
 | 
						|
   */
 | 
						|
  async initFOG() {
 | 
						|
    // Handle Usage Profile ID.  Similar logic to what's happening in
 | 
						|
    // `TelemetryControllerParent` for the client ID.  Must be done before
 | 
						|
    // initializing FOG so that ping enabled/disabled states are correct
 | 
						|
    // before Glean takes actions.
 | 
						|
    await lazy.UsageReporting.ensureInitialized();
 | 
						|
 | 
						|
    // If needed, delay initializing FOG until policy interaction is
 | 
						|
    // completed.  See comments in `TelemetryReportingPolicy`.
 | 
						|
    await lazy.TelemetryReportingPolicy.ensureUserIsNotified();
 | 
						|
 | 
						|
    Services.fog.initializeFOG();
 | 
						|
 | 
						|
    // Register Glean to listen for experiment updates releated to the
 | 
						|
    // "gleanInternalSdk" feature defined in the t/c/nimbus/FeatureManifest.yaml
 | 
						|
    // This feature is intended for internal Glean use only. For features wishing
 | 
						|
    // to set a remote metric configuration, please use the "glean" feature for
 | 
						|
    // the purpose of setting the data-control-plane features via Server Knobs.
 | 
						|
    lazy.NimbusFeatures.gleanInternalSdk.onUpdate(() => {
 | 
						|
      let cfg = lazy.NimbusFeatures.gleanInternalSdk.getVariable(
 | 
						|
        "gleanMetricConfiguration"
 | 
						|
      );
 | 
						|
      Services.fog.applyServerKnobsConfig(JSON.stringify(cfg));
 | 
						|
    });
 | 
						|
 | 
						|
    // Register Glean to listen for experiment updates releated to the
 | 
						|
    // "glean" feature defined in the t/c/nimbus/FeatureManifest.yaml
 | 
						|
    lazy.NimbusFeatures.glean.onUpdate(() => {
 | 
						|
      const enrollments = lazy.NimbusFeatures.glean.getAllEnrollments();
 | 
						|
      for (const enrollment of enrollments) {
 | 
						|
        const cfg = enrollment.value.gleanMetricConfiguration;
 | 
						|
        if (typeof cfg === "object" && cfg !== null) {
 | 
						|
          Services.fog.applyServerKnobsConfig(JSON.stringify(cfg));
 | 
						|
        }
 | 
						|
      }
 | 
						|
    });
 | 
						|
  },
 | 
						|
 | 
						|
  startupConditions() {
 | 
						|
    let nowSeconds = Math.round(Date.now() / 1000);
 | 
						|
    // Don't include cases where we don't have the pref. This rules out the first install
 | 
						|
    // as well as the first run of a build since this was introduced. These could by some
 | 
						|
    // definitions be referred to as "cold" startups, but probably not since we likely
 | 
						|
    // just wrote many of the files we use to disk. This way we should approximate a lower
 | 
						|
    // bound to the number of cold startups rather than an upper bound.
 | 
						|
    let lastCheckSeconds = Services.prefs.getIntPref(
 | 
						|
      "browser.startup.lastColdStartupCheck",
 | 
						|
      nowSeconds
 | 
						|
    );
 | 
						|
    Services.prefs.setIntPref(
 | 
						|
      "browser.startup.lastColdStartupCheck",
 | 
						|
      nowSeconds
 | 
						|
    );
 | 
						|
    try {
 | 
						|
      let secondsSinceLastOSRestart =
 | 
						|
        Services.startup.secondsSinceLastOSRestart;
 | 
						|
      let isColdStartup =
 | 
						|
        nowSeconds - secondsSinceLastOSRestart > lastCheckSeconds;
 | 
						|
      Glean.startup.isCold.set(isColdStartup);
 | 
						|
      Glean.startup.secondsSinceLastOsRestart.set(secondsSinceLastOSRestart);
 | 
						|
    } catch (ex) {
 | 
						|
      if (ex.name !== "NS_ERROR_NOT_IMPLEMENTED") {
 | 
						|
        console.error(ex);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  },
 | 
						|
 | 
						|
  contentBlocking() {
 | 
						|
    let tpEnabled = Services.prefs.getBoolPref(
 | 
						|
      "privacy.trackingprotection.enabled"
 | 
						|
    );
 | 
						|
    Glean.contentblocking.trackingProtectionEnabled[
 | 
						|
      tpEnabled ? "true" : "false"
 | 
						|
    ].add();
 | 
						|
 | 
						|
    let tpPBEnabled = Services.prefs.getBoolPref(
 | 
						|
      "privacy.trackingprotection.pbmode.enabled"
 | 
						|
    );
 | 
						|
    Glean.contentblocking.trackingProtectionPbmDisabled[
 | 
						|
      !tpPBEnabled ? "true" : "false"
 | 
						|
    ].add();
 | 
						|
 | 
						|
    let cookieBehavior = Services.prefs.getIntPref(
 | 
						|
      "network.cookie.cookieBehavior"
 | 
						|
    );
 | 
						|
    Glean.contentblocking.cookieBehavior.accumulateSingleSample(cookieBehavior);
 | 
						|
 | 
						|
    let fpEnabled = Services.prefs.getBoolPref(
 | 
						|
      "privacy.trackingprotection.fingerprinting.enabled"
 | 
						|
    );
 | 
						|
    let cmEnabled = Services.prefs.getBoolPref(
 | 
						|
      "privacy.trackingprotection.cryptomining.enabled"
 | 
						|
    );
 | 
						|
    let categoryPref;
 | 
						|
    switch (
 | 
						|
      Services.prefs.getStringPref("browser.contentblocking.category", null)
 | 
						|
    ) {
 | 
						|
      case "standard":
 | 
						|
        categoryPref = 0;
 | 
						|
        break;
 | 
						|
      case "strict":
 | 
						|
        categoryPref = 1;
 | 
						|
        break;
 | 
						|
      case "custom":
 | 
						|
        categoryPref = 2;
 | 
						|
        break;
 | 
						|
      default:
 | 
						|
        // Any other value is unsupported.
 | 
						|
        categoryPref = 3;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    Glean.contentblocking.fingerprintingBlockingEnabled.set(fpEnabled);
 | 
						|
    Glean.contentblocking.cryptominingBlockingEnabled.set(cmEnabled);
 | 
						|
    Glean.contentblocking.category.set(categoryPref);
 | 
						|
  },
 | 
						|
 | 
						|
  dataSanitization() {
 | 
						|
    Glean.datasanitization.privacySanitizeSanitizeOnShutdown.set(
 | 
						|
      Services.prefs.getBoolPref("privacy.sanitize.sanitizeOnShutdown")
 | 
						|
    );
 | 
						|
    Glean.datasanitization.privacyClearOnShutdownCookies.set(
 | 
						|
      Services.prefs.getBoolPref("privacy.clearOnShutdown.cookies")
 | 
						|
    );
 | 
						|
    Glean.datasanitization.privacyClearOnShutdownHistory.set(
 | 
						|
      Services.prefs.getBoolPref("privacy.clearOnShutdown.history")
 | 
						|
    );
 | 
						|
    Glean.datasanitization.privacyClearOnShutdownFormdata.set(
 | 
						|
      Services.prefs.getBoolPref("privacy.clearOnShutdown.formdata")
 | 
						|
    );
 | 
						|
    Glean.datasanitization.privacyClearOnShutdownDownloads.set(
 | 
						|
      Services.prefs.getBoolPref("privacy.clearOnShutdown.downloads")
 | 
						|
    );
 | 
						|
    Glean.datasanitization.privacyClearOnShutdownCache.set(
 | 
						|
      Services.prefs.getBoolPref("privacy.clearOnShutdown.cache")
 | 
						|
    );
 | 
						|
    Glean.datasanitization.privacyClearOnShutdownSessions.set(
 | 
						|
      Services.prefs.getBoolPref("privacy.clearOnShutdown.sessions")
 | 
						|
    );
 | 
						|
    Glean.datasanitization.privacyClearOnShutdownOfflineApps.set(
 | 
						|
      Services.prefs.getBoolPref("privacy.clearOnShutdown.offlineApps")
 | 
						|
    );
 | 
						|
    Glean.datasanitization.privacyClearOnShutdownSiteSettings.set(
 | 
						|
      Services.prefs.getBoolPref("privacy.clearOnShutdown.siteSettings")
 | 
						|
    );
 | 
						|
    Glean.datasanitization.privacyClearOnShutdownOpenWindows.set(
 | 
						|
      Services.prefs.getBoolPref("privacy.clearOnShutdown.openWindows")
 | 
						|
    );
 | 
						|
 | 
						|
    let exceptions = 0;
 | 
						|
    for (let permission of Services.perms.all) {
 | 
						|
      // We consider just permissions set for http, https and file URLs.
 | 
						|
      if (
 | 
						|
        permission.type == "cookie" &&
 | 
						|
        permission.capability == Ci.nsICookiePermission.ACCESS_SESSION &&
 | 
						|
        ["http", "https", "file"].some(scheme =>
 | 
						|
          permission.principal.schemeIs(scheme)
 | 
						|
        )
 | 
						|
      ) {
 | 
						|
        exceptions++;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    Glean.datasanitization.sessionPermissionExceptions.set(exceptions);
 | 
						|
  },
 | 
						|
 | 
						|
  httpsOnlyState() {
 | 
						|
    const PREF_ENABLED = "dom.security.https_only_mode";
 | 
						|
    const PREF_WAS_ENABLED = "dom.security.https_only_mode_ever_enabled";
 | 
						|
    const _checkHTTPSOnlyPref = async () => {
 | 
						|
      const enabled = Services.prefs.getBoolPref(PREF_ENABLED, false);
 | 
						|
      const was_enabled = Services.prefs.getBoolPref(PREF_WAS_ENABLED, false);
 | 
						|
      let value = 0;
 | 
						|
      if (enabled) {
 | 
						|
        value = 1;
 | 
						|
        Services.prefs.setBoolPref(PREF_WAS_ENABLED, true);
 | 
						|
      } else if (was_enabled) {
 | 
						|
        value = 2;
 | 
						|
      }
 | 
						|
      Glean.security.httpsOnlyModeEnabled.set(value);
 | 
						|
    };
 | 
						|
 | 
						|
    Services.prefs.addObserver(PREF_ENABLED, _checkHTTPSOnlyPref);
 | 
						|
    _checkHTTPSOnlyPref();
 | 
						|
 | 
						|
    const PREF_PBM_WAS_ENABLED =
 | 
						|
      "dom.security.https_only_mode_ever_enabled_pbm";
 | 
						|
    const PREF_PBM_ENABLED = "dom.security.https_only_mode_pbm";
 | 
						|
 | 
						|
    const _checkHTTPSOnlyPBMPref = async () => {
 | 
						|
      const enabledPBM = Services.prefs.getBoolPref(PREF_PBM_ENABLED, false);
 | 
						|
      const was_enabledPBM = Services.prefs.getBoolPref(
 | 
						|
        PREF_PBM_WAS_ENABLED,
 | 
						|
        false
 | 
						|
      );
 | 
						|
      let valuePBM = 0;
 | 
						|
      if (enabledPBM) {
 | 
						|
        valuePBM = 1;
 | 
						|
        Services.prefs.setBoolPref(PREF_PBM_WAS_ENABLED, true);
 | 
						|
      } else if (was_enabledPBM) {
 | 
						|
        valuePBM = 2;
 | 
						|
      }
 | 
						|
      Glean.security.httpsOnlyModeEnabledPbm.set(valuePBM);
 | 
						|
    };
 | 
						|
 | 
						|
    Services.prefs.addObserver(PREF_PBM_ENABLED, _checkHTTPSOnlyPBMPref);
 | 
						|
    _checkHTTPSOnlyPBMPref();
 | 
						|
  },
 | 
						|
 | 
						|
  globalPrivacyControl() {
 | 
						|
    const FEATURE_PREF_ENABLED = "privacy.globalprivacycontrol.enabled";
 | 
						|
    const FUNCTIONALITY_PREF_ENABLED =
 | 
						|
      "privacy.globalprivacycontrol.functionality.enabled";
 | 
						|
    const PREF_WAS_ENABLED = "privacy.globalprivacycontrol.was_ever_enabled";
 | 
						|
    const _checkGPCPref = async () => {
 | 
						|
      const feature_enabled = Services.prefs.getBoolPref(
 | 
						|
        FEATURE_PREF_ENABLED,
 | 
						|
        false
 | 
						|
      );
 | 
						|
      const functionality_enabled = Services.prefs.getBoolPref(
 | 
						|
        FUNCTIONALITY_PREF_ENABLED,
 | 
						|
        false
 | 
						|
      );
 | 
						|
      const was_enabled = Services.prefs.getBoolPref(PREF_WAS_ENABLED, false);
 | 
						|
      let value = 0;
 | 
						|
      if (feature_enabled && functionality_enabled) {
 | 
						|
        value = 1;
 | 
						|
        Services.prefs.setBoolPref(PREF_WAS_ENABLED, true);
 | 
						|
      } else if (was_enabled) {
 | 
						|
        value = 2;
 | 
						|
      }
 | 
						|
      Glean.security.globalPrivacyControlEnabled.set(value);
 | 
						|
    };
 | 
						|
 | 
						|
    Services.prefs.addObserver(FEATURE_PREF_ENABLED, _checkGPCPref);
 | 
						|
    Services.prefs.addObserver(FUNCTIONALITY_PREF_ENABLED, _checkGPCPref);
 | 
						|
    _checkGPCPref();
 | 
						|
  },
 | 
						|
 | 
						|
  async pinningStatus() {
 | 
						|
    let shellService = Cc["@mozilla.org/browser/shell-service;1"].getService(
 | 
						|
      Ci.nsIWindowsShellService
 | 
						|
    );
 | 
						|
    let winTaskbar = Cc["@mozilla.org/windows-taskbar;1"].getService(
 | 
						|
      Ci.nsIWinTaskbar
 | 
						|
    );
 | 
						|
 | 
						|
    try {
 | 
						|
      Glean.osEnvironment.isTaskbarPinned.set(
 | 
						|
        await shellService.isCurrentAppPinnedToTaskbarAsync(
 | 
						|
          winTaskbar.defaultGroupId
 | 
						|
        )
 | 
						|
      );
 | 
						|
      // Bug 1911343: Pinning regular browsing on MSIX
 | 
						|
      // causes false positives when checking for private
 | 
						|
      // browsing.
 | 
						|
      if (
 | 
						|
        AppConstants.platform === "win" &&
 | 
						|
        !Services.sysinfo.getProperty("hasWinPackageId")
 | 
						|
      ) {
 | 
						|
        Glean.osEnvironment.isTaskbarPinnedPrivate.set(
 | 
						|
          await shellService.isCurrentAppPinnedToTaskbarAsync(
 | 
						|
            winTaskbar.defaultPrivateGroupId
 | 
						|
          )
 | 
						|
        );
 | 
						|
      }
 | 
						|
    } catch (ex) {
 | 
						|
      console.error(ex);
 | 
						|
    }
 | 
						|
 | 
						|
    let classification;
 | 
						|
    let shortcut;
 | 
						|
    try {
 | 
						|
      shortcut = Services.appinfo.processStartupShortcut;
 | 
						|
      classification = shellService.classifyShortcut(shortcut);
 | 
						|
    } catch (ex) {
 | 
						|
      console.error(ex);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!classification) {
 | 
						|
      if (lazy.BrowserInitState.isLaunchOnLogin) {
 | 
						|
        classification = "Autostart";
 | 
						|
      } else if (shortcut) {
 | 
						|
        classification = "OtherShortcut";
 | 
						|
      } else {
 | 
						|
        classification = "Other";
 | 
						|
      }
 | 
						|
    }
 | 
						|
    // Because of how taskbar tabs work, it may be classifed as a taskbar
 | 
						|
    // shortcut, in which case we want to overwrite it.
 | 
						|
    if (lazy.BrowserInitState.isTaskbarTab) {
 | 
						|
      classification = "TaskbarTab";
 | 
						|
    }
 | 
						|
    Glean.osEnvironment.launchMethod.set(classification);
 | 
						|
  },
 | 
						|
 | 
						|
  isDefaultHandler() {
 | 
						|
    // Report whether Firefox is the default handler for various files types
 | 
						|
    // and protocols, in particular, ".pdf" and "mailto"
 | 
						|
    [".pdf", "mailto"].every(x => {
 | 
						|
      Glean.osEnvironment.isDefaultHandler[x].set(
 | 
						|
        lazy.ShellService.isDefaultHandlerFor(x)
 | 
						|
      );
 | 
						|
      return true;
 | 
						|
    });
 | 
						|
  },
 | 
						|
 | 
						|
  macDockStatus() {
 | 
						|
    // Report macOS Dock status
 | 
						|
    Glean.osEnvironment.isKeptInDock.set(
 | 
						|
      Cc["@mozilla.org/widget/macdocksupport;1"].getService(
 | 
						|
        Ci.nsIMacDockSupport
 | 
						|
      ).isAppInDock
 | 
						|
    );
 | 
						|
  },
 | 
						|
 | 
						|
  sslKeylogFile() {
 | 
						|
    Glean.sslkeylogging.enabled.set(Services.env.exists("SSLKEYLOGFILE"));
 | 
						|
  },
 | 
						|
 | 
						|
  osAuthEnabled() {
 | 
						|
    // Manually read these prefs. This treats any non-empty-string
 | 
						|
    // value as "turned off", irrespective of whether it correctly
 | 
						|
    // decrypts to the correct value, because we cannot do the
 | 
						|
    // decryption if the primary password has not yet been provided,
 | 
						|
    // and for telemetry treating that situation as "turned off"
 | 
						|
    // seems reasonable.
 | 
						|
    const osAuthForCc = !Services.prefs.getStringPref(
 | 
						|
      lazy.FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF,
 | 
						|
      ""
 | 
						|
    );
 | 
						|
    const osAuthForPw = !Services.prefs.getStringPref(
 | 
						|
      lazy.LoginHelper.OS_AUTH_FOR_PASSWORDS_PREF,
 | 
						|
      ""
 | 
						|
    );
 | 
						|
 | 
						|
    Glean.formautofill.osAuthEnabled.set(osAuthForCc);
 | 
						|
    Glean.pwmgr.osAuthEnabled.set(osAuthForPw);
 | 
						|
  },
 | 
						|
 | 
						|
  primaryPasswordEnabled() {
 | 
						|
    let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"].getService(
 | 
						|
      Ci.nsIPK11TokenDB
 | 
						|
    );
 | 
						|
    let token = tokenDB.getInternalKeyToken();
 | 
						|
    Glean.primaryPassword.enabled.set(token.hasPassword);
 | 
						|
  },
 | 
						|
 | 
						|
  trustObjectCount() {
 | 
						|
    let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
 | 
						|
      Ci.nsIX509CertDB
 | 
						|
    );
 | 
						|
    // countTrustObjects also logs the number of trust objects for telemetry purposes
 | 
						|
    certdb.countTrustObjects();
 | 
						|
  },
 | 
						|
 | 
						|
  pipEnabled() {
 | 
						|
    const TOGGLE_ENABLED_PREF =
 | 
						|
      "media.videocontrols.picture-in-picture.video-toggle.enabled";
 | 
						|
 | 
						|
    const observe = (subject, topic) => {
 | 
						|
      const enabled = Services.prefs.getBoolPref(TOGGLE_ENABLED_PREF, false);
 | 
						|
      Glean.pictureinpicture.toggleEnabled.set(enabled);
 | 
						|
 | 
						|
      // Record events when preferences change
 | 
						|
      if (topic === "nsPref:changed") {
 | 
						|
        if (enabled) {
 | 
						|
          Glean.pictureinpictureSettings.enableSettings.record();
 | 
						|
        }
 | 
						|
      }
 | 
						|
    };
 | 
						|
 | 
						|
    Services.prefs.addObserver(TOGGLE_ENABLED_PREF, observe);
 | 
						|
    observe();
 | 
						|
  },
 | 
						|
};
 |