HPKEConfigManager.sys.mjs (2333B)
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 file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 let knownConfigs = new Map(); 6 7 export class HPKEConfigManager { 8 /** 9 * Decodes a base64url-encoded key string. 10 * 11 * @param {string} aBase64Key 12 * @returns {Uint8Array} 13 */ 14 static decodeKey(aBase64Key) { 15 return new Uint8Array( 16 ChromeUtils.base64URLDecode(aBase64Key, { padding: "ignore" }) 17 ); 18 } 19 20 static async get(aURL, aOptions = {}) { 21 // If we're in a child, forward to the parent. 22 let { remoteType } = Services.appinfo; 23 if (remoteType) { 24 if (remoteType != "privilegedabout") { 25 // The remoteTypes definition in the actor definition will enforce 26 // that calling getActor fails, this is a more readable error: 27 throw new Error( 28 "HPKEConfigManager cannot be used outside of the privilegedabout process." 29 ); 30 } 31 let actor = ChromeUtils.domProcessChild.getActor("HPKEConfigManager"); 32 return actor.sendQuery("getconfig", { url: aURL, options: aOptions }); 33 } 34 try { 35 let config = await this.#getInternal(aURL, aOptions); 36 return new Uint8Array(config); 37 } catch (ex) { 38 console.error(ex); 39 return null; 40 } 41 } 42 43 static async #getInternal(aURL, aOptions = {}) { 44 let { maxAge = -1 } = aOptions; 45 let knownConfig = knownConfigs.get(aURL); 46 if ( 47 knownConfig && 48 (maxAge < 0 || Date.now() - knownConfig.fetchDate < maxAge) 49 ) { 50 return knownConfig.config; 51 } 52 return this.#fetchAndStore(aURL, aOptions); 53 } 54 55 static async #fetchAndStore(aURL, aOptions = {}) { 56 let fetchDate = Date.now(); 57 let resp = await fetch(aURL, { signal: aOptions.abortSignal }); 58 if (!resp?.ok) { 59 throw new Error( 60 `Fetching HPKE config from ${aURL} failed with error ${resp.status}` 61 ); 62 } 63 let config = await resp.blob().then(b => b.arrayBuffer()); 64 knownConfigs.set(aURL, { config, fetchDate }); 65 return config; 66 } 67 } 68 69 export class HPKEConfigManagerParent extends JSProcessActorParent { 70 receiveMessage(msg) { 71 if (msg.name == "getconfig") { 72 return HPKEConfigManager.get(msg.data.url, msg.data.options); 73 } 74 return null; 75 } 76 }