diff --git a/browser/base/content/browser-init.js b/browser/base/content/browser-init.js index 1cfa4b8497..bdf8d7202e 100644 --- a/browser/base/content/browser-init.js +++ b/browser/base/content/browser-init.js @@ -3,6 +3,16 @@ * 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/. */ +const { AddonManager } = ChromeUtils.importESModule( + "resource://gre/modules/AddonManager.sys.mjs", + { global: "shared" } +); +const { FileUtils } = ChromeUtils.importESModule( + "resource://gre/modules/FileUtils.sys.mjs", + { global: "contextual" } +); + + let _resolveDelayedStartup; var delayedStartupPromise = new Promise(resolve => { _resolveDelayedStartup = resolve; @@ -72,7 +82,7 @@ var gBrowserInit = { updateBookmarkToolbarVisibility(); // Set a sane starting width/height for all resolutions on new profiles. - if (ChromeUtils.shouldResistFingerprinting("RoundWindowSize", null)) { + if (true || ChromeUtils.shouldResistFingerprinting("RoundWindowSize", null)) { // When the fingerprinting resistance is enabled, making sure that we don't // have a maximum window to interfere with generating rounded window dimensions. document.documentElement.setAttribute("sizemode", "normal"); @@ -366,9 +417,152 @@ var gBrowserInit = { )?.removeAttribute("key"); } + // Set default size + window.resizeTo(1280, 1040); + + // Hijack the outer window size + let outerWidth, outerHeight; + if ((outerWidth = ChromeUtils.camouGetInt("window.outerWidth"))) { + document.documentElement.style.setProperty('width', outerWidth + 'px'); + browser.style.setProperty('width', outerWidth + 'px'); + window.resizeTo(outerWidth, window.outerHeight); + } + if ((outerHeight = ChromeUtils.camouGetInt("window.outerHeight"))) { + document.documentElement.style.setProperty('height', outerHeight + 'px'); + browser.style.setProperty('height', outerHeight + 'px'); + window.resizeTo(window.outerWidth, outerHeight); + } + browser.style.setProperty('box-sizing', 'content-box'); + + // Hijack the inner window size + let innerWidth = ChromeUtils.camouGetInt("window.innerWidth") || ChromeUtils.camouGetInt("document.body.clientWidth"); + let innerHeight = ChromeUtils.camouGetInt("window.innerHeight") || ChromeUtils.camouGetInt("document.body.clientHeight"); + + if (innerWidth || innerHeight) { + let win_inner_style = document.createElement('style'); + win_inner_style.innerHTML = ` + .browserStack { + ${innerWidth ? `width: ${innerWidth}px !important;` : ''} + ${innerHeight ? `height: ${innerHeight}px !important;` : ''} + ${innerHeight ? `flex: unset !important;` : ''} + overflow: auto; + contain: size; + scrollbar-width: none; + } + `; + document.head.appendChild(win_inner_style); + } + + if (innerWidth && innerHeight && !(outerWidth || outerHeight)) { + let stackRect = __browserStack.getBoundingClientRect(); + let toolbarTop = stackRect.y; + window.resizeBy(width - innerWidth, height + toolbarTop - innerHeight); + } + + // Install addons if specified + let addonPaths = ChromeUtils.camouGetStringList("addons"); + if (addonPaths?.length) { + Promise.all(addonPaths.map(path => this.installTemporaryAddon(path))) + .then(addons => ChromeUtils.camouDebug("Installed " + addons.length + " addon(s)")) + .catch(e => ChromeUtils.camouDebug("Failed to install addons: " + e)); + } + + // Certificate handling + let certsPaths = ChromeUtils.camouGetStringList("certificatePaths"); + let certsRaw = ChromeUtils.camouGetStringList("certificates"); + + if (certsPaths?.length || certsRaw?.length) { + ChromeUtils.camouDebug("Found certificates to import"); + // Set up certificate database + var certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(Ci.nsIX509CertDB); + var certdb2 = certdb; + try { + certdb2 = Cc["@mozilla.org/security/x509certdb;1"].getService(Ci.nsIX509CertDB2); + } catch (e) {} + + // Handle certificate files if any + if (certsPaths?.length) { + ChromeUtils.camouDebug("Processing " + certsPaths.length + " certificate files"); + Promise.all(certsPaths.map(path => this.readCertFile(path))) + .then(certDataArray => { + // Import each certificate using map + certDataArray.map(certData => + this.importCertificate(certdb2, certData, "from file") + ); + }) + .catch(e => ChromeUtils.camouDebug("Failed to read certificate files: " + e)); + } + + // Handle raw certificate strings if any + if (certsRaw?.length) { + ChromeUtils.camouDebug("Processing " + certsRaw.length + " raw certificates"); + // Process all raw certificates using map + certsRaw.map(rawCert => { + try { + let certData = this.processRawCertificate(rawCert); + ChromeUtils.camouDebug("Importing raw certificate: " + certData); + this.importCertificate(certdb2, certData, "raw"); + } catch (e) { + ChromeUtils.camouDebug("Failed to process raw certificate: " + e); + } + }); + } + } + this._loadHandled = true; }, + importCertificate(certdb, certData, source) { + try { + certdb.addCertFromBase64(certData, "C,C,C", ""); + ChromeUtils.camouDebug("Successfully imported " + source + " certificate"); + } catch (e) { + ChromeUtils.camouDebug("Failed to import " + source + " certificate: " + e); + } + }, + + processRawCertificate(content) { + // Process the certificate content (remove markers and newlines) + return content.replace(/\-{5}[\w]+\s[\w]+\-{5}/g, "").replace(/\s/g, ""); + }, + + async readCertFile(path) { + try { + ChromeUtils.camouDebug("Reading certificate file: " + path); + const file = new FileUtils.File(path); + const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); + const channel = ioService.newChannelFromURI( + ioService.newFileURI(file), + null, + Services.scriptSecurityManager.getSystemPrincipal(), + null, + Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, + Ci.nsIContentPolicy.TYPE_OTHER + ); + + const inputStream = Cc["@mozilla.org/scriptableinputstream;1"] + .createInstance(Ci.nsIScriptableInputStream); + const input = channel.open(); + inputStream.init(input); + + let content = inputStream.read(input.available()); + inputStream.close(); + input.close(); + + return this.processRawCertificate(content); + } catch (e) { + ChromeUtils.camouDebug("Error reading certificate file: " + e); + throw e; + } + }, + + async installTemporaryAddon(addonPath) { + const addonFile = new FileUtils.File(addonPath); + const addon = await AddonManager.installTemporaryAddon(addonFile); + Services.obs.notifyObservers(null, "devtools-installed-addon", addon.id); + return addon; + }, + _cancelDelayedStartup() { window.removeEventListener("MozAfterPaint", this._boundDelayedStartup); this._boundDelayedStartup = null;