tor-browser

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

NetworkDecodedBodySizeMap.sys.mjs (3494B)


      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 /**
      6 * This map will return the default value of 0 if the decoded body size for
      7 * a given channel was not received yet.
      8 *
      9 * Bug 1959614: The NetworkDecodedBodySizeMap used to setup promises to wait for
     10 * the decoded body size to be ready. However the timing differences from this
     11 * change leads to regressions in Playwright tests. The new implementation of
     12 * the map is only synchronous and if the size was not received yet, 0 will be
     13 * returned. In theory, the decoded body size should be set via
     14 * http-on-before-stop-request which should be received before the request is
     15 * stopped.
     16 */
     17 export class NetworkDecodedBodySizeMap {
     18  #authenticationAttemptsMap;
     19  #channelIdToBodySizeMap;
     20 
     21  constructor() {
     22    this.#authenticationAttemptsMap = new Map();
     23    this.#channelIdToBodySizeMap = new Map();
     24  }
     25 
     26  destroy() {
     27    // Reset both maps rather than making them null to avoid errors in case any
     28    // API is called after the helper was destroyed.
     29    this.#authenticationAttemptsMap = new Map();
     30    this.#channelIdToBodySizeMap = new Map();
     31  }
     32 
     33  getDecodedBodySize(channelId) {
     34    const decodedBodySize = this.#channelIdToBodySizeMap.get(channelId);
     35    return typeof decodedBodySize === "number" ? decodedBodySize : 0;
     36  }
     37 
     38  /**
     39   * For authentication attempts for the same request, keep track of the
     40   * authentication chain in order to resolve the final getDecodedBodySize when
     41   * the information is received from the content process.
     42   *
     43   * @param {number} previousChannelId
     44   *     The channel ID of the previous channel in the authentication chain.
     45   * @param {number} nextChannelId
     46   *     The channel ID of the new channel in the authentication chain.
     47   */
     48  setAuthenticationAttemptMapping(previousChannelId, nextChannelId) {
     49    if (previousChannelId === nextChannelId) {
     50      // If the preference network.auth.use_redirect_for_retries is set to false
     51      // all channels in the authentication chain will share the same channelId.
     52      // In this case there is no need to set anything in the map, the content
     53      // size will be set for the correct channelId by design.
     54      return;
     55    }
     56    this.#authenticationAttemptsMap.set(previousChannelId, nextChannelId);
     57  }
     58 
     59  /**
     60   * Set the decodedBodySize for the provided channelId. If the channel is part
     61   * of an authentication chain, the decoded body size will instead be set for
     62   * the current channel of the chain.
     63   *
     64   * @param {number} channelId
     65   *     The id of the channel to update.
     66   * @param {number} decodedBodySize
     67   *     The decoded body size for the channel.
     68   */
     69  setDecodedBodySize(channelId, decodedBodySize) {
     70    if (this.#authenticationAttemptsMap.has(channelId)) {
     71      // If there is an auth chain for this channel, setDecodedBodySize will be
     72      // called for the original channel ID. Traverse the authentication attempt
     73      // map to set the decoded body size for the current channel in the chain.
     74      this.setDecodedBodySize(
     75        this.#authenticationAttemptsMap.get(channelId),
     76        decodedBodySize
     77      );
     78      return;
     79    }
     80 
     81    this.#channelIdToBodySizeMap.set(channelId, decodedBodySize);
     82  }
     83 
     84  delete(channelId) {
     85    this.#authenticationAttemptsMap.delete(channelId);
     86    this.#channelIdToBodySizeMap.delete(channelId);
     87  }
     88 }