tor-browser

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

NetworkCacheManager.sys.mjs (4811B)


      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 const lazy = {};
      6 
      7 ChromeUtils.defineESModuleGetters(lazy, {
      8  BrowsingContextListener:
      9    "chrome://remote/content/shared/listeners/BrowsingContextListener.sys.mjs",
     10  TabManager: "chrome://remote/content/shared/TabManager.sys.mjs",
     11 });
     12 
     13 /**
     14 * Enum of possible network cache behaviors.
     15 *
     16 * @readonly
     17 * @enum {CacheBehavior}
     18 */
     19 export const CacheBehavior = {
     20  Default: "default",
     21  Bypass: "bypass",
     22 };
     23 
     24 /**
     25 * The NetworkCacheManager is responsible for managing the cache status (enabling/disabling cache)
     26 * for navigables. It's meant to be a singleton, and the consumers can use the exported
     27 * methods to change the cache status or perform the state cleanup.
     28 *
     29 * @class NetworkCacheManager
     30 */
     31 class NetworkCacheManager {
     32  #contextListener;
     33  #defaultCacheBehavior;
     34  #navigableCacheBehaviorMap;
     35 
     36  constructor() {
     37    this.#contextListener = new lazy.BrowsingContextListener();
     38    this.#contextListener.on("attached", this.#onContextAttached);
     39 
     40    this.#defaultCacheBehavior = CacheBehavior.Default;
     41    // WeakMap from navigables to cache behavior settings (CacheBehavior).
     42    this.#navigableCacheBehaviorMap = new WeakMap();
     43  }
     44 
     45  destroy() {
     46    this.#contextListener.off("attached", this.#onContextAttached);
     47    this.#contextListener.destroy();
     48 
     49    this.cleanup();
     50  }
     51 
     52  #getLoadFlags(behavior) {
     53    return behavior === CacheBehavior.Bypass
     54      ? Ci.nsIRequest.LOAD_BYPASS_CACHE
     55      : Ci.nsIRequest.LOAD_NORMAL;
     56  }
     57 
     58  #getWeakMapSize(weakMap) {
     59    return ChromeUtils.nondeterministicGetWeakMapKeys(weakMap).length;
     60  }
     61 
     62  #onContextAttached = (eventName, data = {}) => {
     63    if (this.#defaultCacheBehavior === CacheBehavior.Bypass) {
     64      this.#setLoadFlagsForBrowsingContext(
     65        data.browsingContext,
     66        this.#getLoadFlags(CacheBehavior.Bypass)
     67      );
     68    }
     69  };
     70 
     71  #setDefaultCacheBehavior(behavior) {
     72    this.#defaultCacheBehavior = behavior;
     73    this.#navigableCacheBehaviorMap = new WeakMap();
     74 
     75    const loadFlags = this.#getLoadFlags(behavior);
     76 
     77    // Update cache settings for all existing navigables.
     78    for (const browser of lazy.TabManager.getBrowsers()) {
     79      this.#setLoadFlagsForBrowsingContext(browser.browsingContext, loadFlags);
     80    }
     81 
     82    // In case the cache is globally disabled we have to listen to all
     83    // newly attached contexts and update the cache behavior for them.
     84    if (this.#defaultCacheBehavior === CacheBehavior.Bypass) {
     85      this.#contextListener.startListening();
     86    } else {
     87      this.#contextListener.stopListening();
     88    }
     89  }
     90 
     91  #setLoadFlagsForBrowsingContext(browsingContext, loadFlags) {
     92    if (browsingContext.defaultLoadFlags !== loadFlags) {
     93      browsingContext.defaultLoadFlags = loadFlags;
     94    }
     95  }
     96 
     97  /**
     98   * Reset network cache behavior to the default.
     99   */
    100  cleanup() {
    101    this.#setDefaultCacheBehavior(CacheBehavior.Default);
    102 
    103    if (this.#getWeakMapSize(this.#navigableCacheBehaviorMap) === 0) {
    104      return;
    105    }
    106 
    107    const loadFlags = this.#getLoadFlags(CacheBehavior.Default);
    108 
    109    for (const browser of lazy.TabManager.getBrowsers()) {
    110      if (this.#navigableCacheBehaviorMap.has(browser.browsingContext)) {
    111        this.#setLoadFlagsForBrowsingContext(
    112          browser.browsingContext,
    113          loadFlags
    114        );
    115      }
    116    }
    117 
    118    this.#navigableCacheBehaviorMap = new WeakMap();
    119  }
    120 
    121  /**
    122   * Update network cache behavior to a provided value
    123   * and optionally specified contexts.
    124   *
    125   * @param {CacheBehavior} behavior
    126   *     An enum value to set the network cache behavior.
    127   * @param {Array<BrowsingContext>=} contexts
    128   *     The list of browsing contexts where the network cache
    129   *     behaviour should be updated.
    130   */
    131  updateCacheBehavior(behavior, contexts = null) {
    132    if (contexts === null) {
    133      this.#setDefaultCacheBehavior(behavior);
    134      return;
    135    }
    136 
    137    const loadFlags = this.#getLoadFlags(behavior);
    138 
    139    for (const context of contexts) {
    140      if (this.#navigableCacheBehaviorMap.get(context) === behavior) {
    141        continue;
    142      }
    143 
    144      this.#setLoadFlagsForBrowsingContext(context, loadFlags);
    145 
    146      if (behavior === CacheBehavior.Default) {
    147        this.#navigableCacheBehaviorMap.delete(context);
    148      } else {
    149        this.#navigableCacheBehaviorMap.set(context, behavior);
    150      }
    151    }
    152  }
    153 }
    154 
    155 // Create a private NetworkCacheManager singleton.
    156 const networkCacheManager = new NetworkCacheManager();
    157 
    158 export function updateCacheBehavior(behavior, contexts) {
    159  return networkCacheManager.updateCacheBehavior(behavior, contexts);
    160 }
    161 
    162 export function cleanupCacheBypassState() {
    163  return networkCacheManager.cleanup();
    164 }