Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/toolkit/components/ipprotection/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 7 kB image not shown  

Quelle  IPPStartupCache.sys.mjs   Sprache: unbekannt

 
Spracherkennung für: .mjs vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

/* 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";

const lazy = {};

/**
 * Type Imports
 *
 * @typedef {import("./GuardianTypes.sys.mjs").Entitlement} Entitlement
 * @typedef {import("./GuardianTypes.sys.mjs").ProxyUsage} ProxyUsage
 */
ChromeUtils.defineESModuleGetters(lazy, {
  IPProtectionService:
    "moz-src:///toolkit/components/ipprotection/IPProtectionService.sys.mjs",
  IPProtectionStates:
    "moz-src:///toolkit/components/ipprotection/IPProtectionService.sys.mjs",
  IPPProxyManager:
    "moz-src:///toolkit/components/ipprotection/IPPProxyManager.sys.mjs",
  Entitlement:
    "moz-src:///toolkit/components/ipprotection/GuardianTypes.sys.mjs",
  ProxyUsage:
    "moz-src:///toolkit/components/ipprotection/GuardianTypes.sys.mjs",
});

const STATE_CACHE_PREF = "browser.ipProtection.stateCache";
const ENTITLEMENT_CACHE_PREF = "browser.ipProtection.entitlementCache";
const LOCATIONLIST_CACHE_PREF = "browser.ipProtection.locationListCache";
const USAGE_CACHE_PREF = "browser.ipProtection.usageCache";
const HAS_UPGRADED_PREF = "browser.ipProtection.hasUpgraded";

/**
 * This class implements a cache for the IPP state machine. The cache is used
 * until we receive the `sessionstore-windows-restored` event
 */
class IPPStartupCacheSingleton {
  #stateFromCache = null;
  #startupCompleted = false;

  constructor() {
    // For XPCShell tests, the cache must be disabled.
    if (
      Services.prefs.getBoolPref("browser.ipProtection.cacheDisabled", false)
    ) {
      this.#startupCompleted = true;
      return;
    }

    this.handleEvent = this.#handleEvent.bind(this);

    // Android has no `sessionstore-windows-restored` notification; mark
    // startup as completed so IPProtectionService.init() runs
    // initOnStartupCompleted() synchronously.
    if (AppConstants.platform === "android") {
      this.#startupCompleted = true;
      return;
    }

    const stateFromCache = Services.prefs.getCharPref(
      STATE_CACHE_PREF,
      "unset"
    );
    if (stateFromCache !== "unset") {
      this.#stateFromCache = stateFromCache;
    }

    Services.obs.addObserver(this, "sessionstore-windows-restored");
  }

  init() {
    lazy.IPProtectionService.addEventListener(
      "IPProtectionService:StateChanged",
      this.handleEvent
    );
    lazy.IPPProxyManager.addEventListener(
      "IPPProxyManager:UsageChanged",
      this.handleEvent
    );
  }

  async initOnStartupCompleted() {}

  uninit() {
    lazy.IPProtectionService.removeEventListener(
      "IPProtectionService:StateChanged",
      this.handleEvent
    );
    lazy.IPPProxyManager.removeEventListener(
      "IPPProxyManager:UsageChanged",
      this.handleEvent
    );
  }

  get isStartupCompleted() {
    return this.#startupCompleted;
  }

  get state() {
    if (this.#startupCompleted) {
      throw new Error("IPPStartupCache should not be used after the startup");
    }

    if (Object.values(lazy.IPProtectionStates).includes(this.#stateFromCache)) {
      return this.#stateFromCache;
    }

    // This should not happen.
    return lazy.IPProtectionStates.UNINITIALIZED;
  }

  async observe(_subject, topic, _) {
    if (topic !== "sessionstore-windows-restored") {
      return;
    }

    // The browser is ready! Let's invalidate the cache and let's recompute the
    // state.

    Services.obs.removeObserver(this, "sessionstore-windows-restored");
    this.#startupCompleted = true;
    this.#stateFromCache = null;

    if (
      lazy.IPProtectionService.state !== lazy.IPProtectionStates.UNINITIALIZED
    ) {
      await lazy.IPProtectionService.initOnStartupCompleted();
    }
    lazy.IPProtectionService.updateState();
  }

  /**
   * Stores the entitlement in the cache.
   *
   * @param {Entitlement} entitlement
   */
  storeEntitlement(entitlement) {
    if (!entitlement) {
      Services.prefs.setCharPref(ENTITLEMENT_CACHE_PREF, "");
      Services.prefs.setBoolPref(HAS_UPGRADED_PREF, false);
      return;
    }
    if (entitlement instanceof lazy.Entitlement === false) {
      throw new Error(
        "entitlement must be an instance of Entitlement, is " +
          JSON.stringify(entitlement)
      );
    }
    Services.prefs.setCharPref(ENTITLEMENT_CACHE_PREF, entitlement?.toString());
    Services.prefs.setBoolPref(HAS_UPGRADED_PREF, entitlement.subscribed);
  }

  /**
   * Retrieves the entitlement from the cache.
   *
   * @returns {Entitlement|null}
   */
  get entitlement() {
    try {
      const entitlement_string = Services.prefs.getCharPref(
        ENTITLEMENT_CACHE_PREF,
        ""
      );
      return new lazy.Entitlement(JSON.parse(entitlement_string));
    } catch (e) {
      return null;
    }
  }

  storeLocationList(locationList) {
    Services.prefs.setCharPref(
      LOCATIONLIST_CACHE_PREF,
      JSON.stringify(locationList)
    );
  }

  get locationList() {
    try {
      const locationList = Services.prefs.getCharPref(
        LOCATIONLIST_CACHE_PREF,
        ""
      );
      return JSON.parse(locationList);
    } catch (e) {
      return null;
    }
  }

  /**
   * Stores the usage info in the cache.
   *
   * @param {ProxyUsage} usageInfo
   */
  storeUsageInfo(usageInfo) {
    if (!usageInfo) {
      Services.prefs.setCharPref(USAGE_CACHE_PREF, "");
      return;
    }
    if (usageInfo instanceof lazy.ProxyUsage === false) {
      throw new Error(
        "usageInfo must be an instance of ProxyUsage, is " +
          JSON.stringify(usageInfo, (key, value) =>
            typeof value === "bigint" ? JSON.rawJSON(value.toString()) : value
          )
      );
    }
    const serialized = JSON.stringify({
      max: usageInfo.max?.toString() ?? null,
      remaining: usageInfo.remaining?.toString() ?? null,
      reset: usageInfo.reset?.toString() ?? null,
      unlimited: usageInfo.unlimited,
    });
    Services.prefs.setCharPref(USAGE_CACHE_PREF, serialized);
  }

  /**
   * Retrieves the usage info from the cache.
   *
   * @returns {ProxyUsage|null}
   */
  get usageInfo() {
    try {
      const usageInfo_string = Services.prefs.getCharPref(USAGE_CACHE_PREF, "");
      if (!usageInfo_string) {
        return null;
      }
      const data = JSON.parse(usageInfo_string);
      return new lazy.ProxyUsage(
        data.max,
        data.remaining,
        data.reset,
        data.unlimited ?? false
      );
    } catch (e) {
      return null;
    }
  }

  #handleEvent(event) {
    if (event.type === "IPProtectionService:StateChanged") {
      const state = lazy.IPProtectionService.state;
      if (this.#startupCompleted) {
        Services.prefs.setCharPref(STATE_CACHE_PREF, state);
      } else {
        this.#stateFromCache = state;
      }
    } else if (event.type === "IPPProxyManager:UsageChanged") {
      const usageInfo = event.detail.usage;
      this.storeUsageInfo(usageInfo);
    }
  }
}

const IPPStartupCache = new IPPStartupCacheSingleton();

export { IPPStartupCache, IPPStartupCacheSingleton };

[Dauer der Verarbeitung: 0.29 Sekunden, vorverarbeitet 2026-08-25]