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 }