From df07177f6b648ce047b968189b6e9728b71e3381 Mon Sep 17 00:00:00 2001 From: Julian Descottes Date: Fri, 19 Jun 2026 16:02:59 +0200 Subject: [PATCH] Bug 2044655 - Force app.update.disabledForTesting to true when recommended preferences are disabled --- README.md | 7 ++++++- src/firefox/core.ts | 6 ++++++ tests/firefox/core-prefs.test.ts | 22 ++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7c42dae..3e44102 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,12 @@ You can pass flags or environment variables (names on the right): - `--android-package` — Android app package name, default `org.mozilla.firefox`. Other packages: `org.mozilla.firefox_beta` for Firefox Beta, `org.mozilla.fenix` for Firefox Nightly, `org.mozilla.fenix.debug` for Firefox Nightly Debug, `org.mozilla.geckoview_example` for geckoview (`ANDROID_PACKAGE`) - `--log-file` — write MCP server logs to a file instead of stderr. Useful for debugging sessions with MCP clients that hide server output. Set `DEBUG=*` to also include verbose debug logs. Example: `--log-file /tmp/firefox-mcp.log` -> **Note on `--pref`:** When Firefox runs in automation, it applies [RecommendedPreferences](https://searchfox.org/firefox-main/source/remote/shared/RecommendedPreferences.sys.mjs) that modify browser behavior for testing. The `--pref` option allows overriding these defaults when needed. + +### Useful preferences (`--pref`) + +- remote.prefs.recommended=false. When Firefox runs in automation, it applies [RecommendedPreferences](https://searchfox.org/firefox-main/source/remote/shared/RecommendedPreferences.sys.mjs) that modify browser behavior for testing. Set remote.prefs.recommended to false to skip those and have a configuration closer to a regular Firefox instance. +- remote.log.level=Trace. Enable verbose WebDriver protocol logs in Firefox. The MCP server will automatically pass the matching log level to geckodriver so both sides log at the same verbosity. +- app.update.disabledForTesting=false. Allow Firefox to automatically download and apply updates. Note that updates may interrupt your session. Requires also setting remote.prefs.recommended=false. ### Firefox for Android diff --git a/src/firefox/core.ts b/src/firefox/core.ts index 3966c81..7227fb8 100644 --- a/src/firefox/core.ts +++ b/src/firefox/core.ts @@ -222,6 +222,12 @@ export class FirefoxCore { for (const [name, value] of Object.entries(this.options.prefs)) { firefoxOptions.setPreference(name, value); } + if ( + this.options.prefs['remote.prefs.recommended'] === false && + !('app.update.disabledForTesting' in this.options.prefs) + ) { + firefoxOptions.setPreference('app.update.disabledForTesting', true); + } } let serviceBuilder; diff --git a/tests/firefox/core-prefs.test.ts b/tests/firefox/core-prefs.test.ts index 7de63d4..9fdb961 100644 --- a/tests/firefox/core-prefs.test.ts +++ b/tests/firefox/core-prefs.test.ts @@ -102,6 +102,28 @@ describe('FirefoxCore prefs via firefoxOptions', () => { expect(mockServiceBuilderAddArguments).not.toHaveBeenCalledWith('--log', expect.anything()); }); + it('should automatically set app.update.disabledForTesting when remote.prefs.recommended is false', async () => { + mockSelenium(); + const { FirefoxCore } = await import('../../src/firefox/core.js'); + const core = new FirefoxCore({ + headless: true, + prefs: { 'remote.prefs.recommended': false }, + }); + await core.connect(); + expect(mockSetPreference).toHaveBeenCalledWith('app.update.disabledForTesting', true); + }); + + it('should not override app.update.disabledForTesting when explicitly set alongside remote.prefs.recommended=false', async () => { + mockSelenium(); + const { FirefoxCore } = await import('../../src/firefox/core.js'); + const core = new FirefoxCore({ + headless: true, + prefs: { 'remote.prefs.recommended': false, 'app.update.disabledForTesting': false }, + }); + await core.connect(); + expect(mockSetPreference).not.toHaveBeenCalledWith('app.update.disabledForTesting', true); + }); + it('should not require MOZ_REMOTE_ALLOW_SYSTEM_ACCESS', async () => { delete process.env.MOZ_REMOTE_ALLOW_SYSTEM_ACCESS; mockSelenium();