From 90c3cd6c78683b0c16ec6e2ea4517bce4dac7c87 Mon Sep 17 00:00:00 2001 From: daijro Date: Thu, 21 Nov 2024 16:22:05 -0600 Subject: [PATCH] Load addons without debug server #90 - A list of addons can now be passed with the `addons` property - Merged all browser-init patches into one - Removed the remote cue disabler patch to warn the user if a debug server is enabled --- patches/browser-init.patch | 152 +++++++++++++++++++++++++++++ patches/chromeutil.patch | 49 +++++++--- patches/cursor-highlighter.patch | 36 ------- patches/debug-url-navigation.patch | 27 ----- patches/disable-remote-cue.patch | 13 --- patches/viewport-hijacker.patch | 62 ------------ 6 files changed, 188 insertions(+), 151 deletions(-) create mode 100644 patches/browser-init.patch delete mode 100644 patches/cursor-highlighter.patch delete mode 100644 patches/debug-url-navigation.patch delete mode 100644 patches/disable-remote-cue.patch delete mode 100644 patches/viewport-hijacker.patch diff --git a/patches/browser-init.patch b/patches/browser-init.patch new file mode 100644 index 0000000..7caea46 --- /dev/null +++ b/patches/browser-init.patch @@ -0,0 +1,152 @@ +diff --git a/browser/base/content/browser-init.js b/browser/base/content/browser-init.js +index bb91ab8cfa..7496eb9a58 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"); +@@ -276,6 +286,22 @@ var gBrowserInit = { + // Update UI if browser is under remote control. + gRemoteControl.updateVisualCue(); + ++ // Camoufox: print URL changes to console ++ if (ChromeUtils.isCamouDebug()) { ++ ChromeUtils.camouDebug("Debug mode ON."); ++ gBrowser.addTabsProgressListener({ ++ onLocationChange(aBrowser, aWebProgress, aRequest, aLocation, aFlags) { ++ if (aBrowser === gBrowser.selectedBrowser) { ++ ChromeUtils.camouDebug("URL changed to: " + aLocation.spec); ++ } ++ } ++ }); ++ ++ gURLBar.addEventListener("change", () => { ++ ChromeUtils.camouDebug("URL bar value changed to: " + gURLBar.value); ++ }); ++ } ++ + // If we are given a tab to swap in, take care of it before first paint to + // avoid an about:blank flash. + let tabToAdopt = this.getTabToAdopt(); +@@ -311,6 +337,31 @@ var gBrowserInit = { + } + } + ++ if (ChromeUtils.camouGetBool("showcursor", true)) { ++ let cursorFollower = document.createElement("div"); ++ cursorFollower.id = "cursor-highlighter"; ++ cursorFollower.style.cssText = ` ++ position: fixed; ++ width: 10px; ++ height: 10px; ++ background-color: rgba(255,105,105,0.8); ++ border-radius: 50%; ++ pointer-events: none; ++ z-index: 2147483647; ++ transform: translate(-50%, -50%); ++ box-shadow: ++ 0 0 0 5px rgba(255,105,105,0.5), ++ 0 0 0 10px rgba(255,105,105,0.3), ++ 0 0 0 15px rgba(255,105,105,0.1); ++ `; ++ document.documentElement.appendChild(cursorFollower); ++ ++ window.addEventListener('mousemove', e => { ++ cursorFollower.style.left = `${e.clientX}px`; ++ cursorFollower.style.top = `${e.clientY}px`; ++ }); ++ } ++ + // Wait until chrome is painted before executing code not critical to making the window visible + this._boundDelayedStartup = this._delayedStartup.bind(this); + window.addEventListener("MozAfterPaint", this._boundDelayedStartup); +@@ -332,9 +383,66 @@ 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)); ++ } ++ + this._loadHandled = true; + }, + ++ 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; diff --git a/patches/chromeutil.patch b/patches/chromeutil.patch index 5ab6fd6..7bbdae5 100644 --- a/patches/chromeutil.patch +++ b/patches/chromeutil.patch @@ -1,5 +1,5 @@ diff --git a/dom/base/ChromeUtils.cpp b/dom/base/ChromeUtils.cpp -index 6833d2227f..9f88bd3d34 100644 +index 52f0af76ec..2a7a9ae4fc 100644 --- a/dom/base/ChromeUtils.cpp +++ b/dom/base/ChromeUtils.cpp @@ -5,6 +5,8 @@ @@ -10,8 +10,8 @@ index 6833d2227f..9f88bd3d34 100644 +#include "MouseTrajectories.hpp" #include "JSOracleParent.h" - #include "js/CallAndConstruct.h" // JS::Call -@@ -2068,6 +2070,24 @@ bool ChromeUtils::IsDarkBackground(GlobalObject&, Element& aElement) { + #include "ThirdPartyUtil.h" +@@ -2115,6 +2117,24 @@ bool ChromeUtils::IsDarkBackground(GlobalObject&, Element& aElement) { return nsNativeTheme::IsDarkBackground(f); } @@ -36,7 +36,7 @@ index 6833d2227f..9f88bd3d34 100644 double ChromeUtils::DateNow(GlobalObject&) { return JS_Now() / 1000.0; } /* static */ -@@ -2094,6 +2114,62 @@ void ChromeUtils::GetAllPossibleUtilityActorNames(GlobalObject& aGlobal, +@@ -2141,6 +2161,77 @@ void ChromeUtils::GetAllPossibleUtilityActorNames(GlobalObject& aGlobal, } } @@ -62,9 +62,8 @@ index 6833d2227f..9f88bd3d34 100644 +} + +/* static */ -+bool ChromeUtils::CamouGetBool(GlobalObject& aGlobal, -+ const nsAString& aVarName, -+ bool aDefaultValue) { ++bool ChromeUtils::CamouGetBool(GlobalObject& aGlobal, const nsAString& aVarName, ++ bool aDefaultValue) { + NS_ConvertUTF16toUTF8 utf8VarName(aVarName); + if (auto value = MaskConfig::GetBool(utf8VarName.get())) { + return value.value(); @@ -85,6 +84,22 @@ index 6833d2227f..9f88bd3d34 100644 +} + +/* static */ ++void ChromeUtils::CamouGetStringList(GlobalObject& aGlobal, ++ const nsAString& aVarName, ++ nsTArray& aRetVal) { ++ NS_ConvertUTF16toUTF8 utf8VarName(aVarName); ++ if (auto values = MaskConfig::GetStringList(utf8VarName.get()); ++ !values.empty()) { ++ aRetVal.Clear(); ++ for (const auto& str : values) { ++ aRetVal.AppendElement(NS_ConvertUTF8toUTF16(str)); ++ } ++ return; ++ } ++ aRetVal.Clear(); ++} ++ ++/* static */ +void ChromeUtils::CamouGetMouseTrajectory(GlobalObject& aGlobal, long aFromX, + long aFromY, long aToX, long aToY, + nsTArray& aPoints) { @@ -100,10 +115,10 @@ index 6833d2227f..9f88bd3d34 100644 bool ChromeUtils::ShouldResistFingerprinting( GlobalObject& aGlobal, JSRFPTarget aTarget, diff --git a/dom/base/ChromeUtils.h b/dom/base/ChromeUtils.h -index 0150c59670..3a244a80e4 100644 +index 138b9c3f80..c7c7ce74bf 100644 --- a/dom/base/ChromeUtils.h +++ b/dom/base/ChromeUtils.h -@@ -301,6 +301,10 @@ class ChromeUtils { +@@ -305,6 +305,10 @@ class ChromeUtils { static bool IsDarkBackground(GlobalObject&, Element&); @@ -114,7 +129,7 @@ index 0150c59670..3a244a80e4 100644 static double DateNow(GlobalObject&); static void EnsureJSOracleStarted(GlobalObject&); -@@ -310,6 +314,21 @@ class ChromeUtils { +@@ -314,6 +318,24 @@ class ChromeUtils { static void GetAllPossibleUtilityActorNames(GlobalObject& aGlobal, nsTArray& aNames); @@ -129,6 +144,9 @@ index 0150c59670..3a244a80e4 100644 + static void CamouGetString(GlobalObject& aGlobal, const nsAString& aVarName, + nsAString& aRetVal); + ++ static void CamouGetStringList(GlobalObject& aGlobal, const nsAString& aVarName, ++ nsTArray& aRetVal); ++ + static void CamouGetMouseTrajectory(GlobalObject& aGlobal, long aFromX, + long aFromY, long aToX, long aToY, + nsTArray& aPoints); @@ -137,10 +155,10 @@ index 0150c59670..3a244a80e4 100644 GlobalObject& aGlobal, JSRFPTarget aTarget, const Nullable& aOverriddenFingerprintingSettings); diff --git a/dom/chrome-webidl/ChromeUtils.webidl b/dom/chrome-webidl/ChromeUtils.webidl -index bf196f039d..e134d816b3 100644 +index 6a99703db1..82415eba19 100644 --- a/dom/chrome-webidl/ChromeUtils.webidl +++ b/dom/chrome-webidl/ChromeUtils.webidl -@@ -746,6 +746,13 @@ partial namespace ChromeUtils { +@@ -750,6 +750,13 @@ partial namespace ChromeUtils { */ boolean isDarkBackground(Element element); @@ -154,7 +172,7 @@ index bf196f039d..e134d816b3 100644 /** * Starts the JSOracle process for ORB JavaScript validation, if it hasn't started already. */ -@@ -757,6 +764,31 @@ partial namespace ChromeUtils { +@@ -761,6 +768,36 @@ partial namespace ChromeUtils { [ChromeOnly] readonly attribute unsigned long aliveUtilityProcesses; @@ -179,6 +197,11 @@ index bf196f039d..e134d816b3 100644 + DOMString camouGetString(DOMString varName); + + /** ++ * Get a list of strings from Camoufox MaskConfig. ++ */ ++ sequence camouGetStringList(DOMString varName); ++ ++ /** + * Calculate a human-like mouse trajectory between two points. + */ + sequence camouGetMouseTrajectory(long fromX, long fromY, long toX, long toY); diff --git a/patches/cursor-highlighter.patch b/patches/cursor-highlighter.patch deleted file mode 100644 index de761d7..0000000 --- a/patches/cursor-highlighter.patch +++ /dev/null @@ -1,36 +0,0 @@ -diff --git a/browser/base/content/browser-init.js b/browser/base/content/browser-init.js -index 63c9c39741..cc7fa914c0 100644 ---- a/browser/base/content/browser-init.js -+++ b/browser/base/content/browser-init.js -@@ -292,6 +292,31 @@ var gBrowserInit = { - } - } - -+ if (ChromeUtils.camouGetBool("showcursor", true)) { -+ let cursorFollower = document.createElement("div"); -+ cursorFollower.id = "cursor-highlighter"; -+ cursorFollower.style.cssText = ` -+ position: fixed; -+ width: 10px; -+ height: 10px; -+ background-color: rgba(255,105,105,0.8); -+ border-radius: 50%; -+ pointer-events: none; -+ z-index: 2147483647; -+ transform: translate(-50%, -50%); -+ box-shadow: -+ 0 0 0 5px rgba(255,105,105,0.5), -+ 0 0 0 10px rgba(255,105,105,0.3), -+ 0 0 0 15px rgba(255,105,105,0.1); -+ `; -+ document.documentElement.appendChild(cursorFollower); -+ -+ window.addEventListener('mousemove', e => { -+ cursorFollower.style.left = `${e.clientX}px`; -+ cursorFollower.style.top = `${e.clientY}px`; -+ }); -+ } -+ - // Wait until chrome is painted before executing code not critical to making the window visible - this._boundDelayedStartup = this._delayedStartup.bind(this); - window.addEventListener("MozAfterPaint", this._boundDelayedStartup); diff --git a/patches/debug-url-navigation.patch b/patches/debug-url-navigation.patch deleted file mode 100644 index 50add53..0000000 --- a/patches/debug-url-navigation.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/browser/base/content/browser-init.js b/browser/base/content/browser-init.js -index bee5309c04..3d0df30224 100644 ---- a/browser/base/content/browser-init.js -+++ b/browser/base/content/browser-init.js -@@ -246,6 +246,22 @@ var gBrowserInit = { - // Update UI if browser is under remote control. - gRemoteControl.updateVisualCue(); - -+ // Camoufox: print URL changes to console -+ if (ChromeUtils.isCamouDebug()) { -+ ChromeUtils.camouDebug("Debug mode ON."); -+ gBrowser.addTabsProgressListener({ -+ onLocationChange(aBrowser, aWebProgress, aRequest, aLocation, aFlags) { -+ if (aBrowser === gBrowser.selectedBrowser) { -+ ChromeUtils.camouDebug("URL changed to: " + aLocation.spec); -+ } -+ } -+ }); -+ -+ gURLBar.addEventListener("change", () => { -+ ChromeUtils.camouDebug("URL bar value changed to: " + gURLBar.value); -+ }); -+ } -+ - // If we are given a tab to swap in, take care of it before first paint to - // avoid an about:blank flash. - let tabToAdopt = this.getTabToAdopt(); diff --git a/patches/disable-remote-cue.patch b/patches/disable-remote-cue.patch deleted file mode 100644 index 06932f8..0000000 --- a/patches/disable-remote-cue.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js -index 1d69c20fb5..c34b4c6a88 100644 ---- a/browser/base/content/browser.js -+++ b/browser/base/content/browser.js -@@ -6721,7 +6721,7 @@ const gRemoteControl = { - "browser.chrome.disableRemoteControlCueForTests", - false - ); -- if (disableRemoteControlCue && Cu.isInAutomation) { -+ if (true) { - return; - } - diff --git a/patches/viewport-hijacker.patch b/patches/viewport-hijacker.patch deleted file mode 100644 index cd29edd..0000000 --- a/patches/viewport-hijacker.patch +++ /dev/null @@ -1,62 +0,0 @@ -diff --git a/browser/base/content/browser-init.js b/browser/base/content/browser-init.js -index bee5309c04..d7fa2af364 100644 ---- a/browser/base/content/browser-init.js -+++ b/browser/base/content/browser-init.js -@@ -72,7 +72,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"); -@@ -302,6 +302,48 @@ 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); -+ } -+ - this._loadHandled = true; - }, -