Repository navigation
Android to Firefox 153.4.0esr (security), Mullvad DoH migration, uBO startup fixes - #2
Merged
Merged
Conversation
Moves the settings submodule 6b41a31 -> 0cae8fb (branch android-esr-153.4). Android only; common.cfg, desktop.cfg and librewolf.cfg are byte-identical, so desktop is unaffected. Android now takes upstream's value for doh-rollout.provider-list (Mullvad removed), toolkit.telemetry.cachedClientID (locked canary UUID instead of ""), browser.cache.disk.encryption.enabled (true) and librewolf.uBO.assetsBootstrapLocation (librewolf.dev; verified HTTP 200 and byte-identical to the codeberg body). app.releaseNotesURL points at https://github.com/CPlusPlus17/Redoubt/releases. board.py CFG_EXPECTED is unchanged: it counts common.cfg + desktop.cfg only, and neither changed. android.cfg goes from 24 to 20 calls. python3 docs/android/board.py --check-cfg-split ok: 181 common / 200 desktop / 20 android calls; librewolf.cfg regenerates exactly python3 docs/android/board.py --check ok scripts/tests/test-android-parity-gates.py 29 tests OK android-network-check.sh / android-rfp-check.sh --self-test passed Not changed here: patches/android/privacy-defaults.patch still carries Mullvad in its hand-kept Kotlin copy of the DoH list (the Fenix picker reads that, not the pref); that and the user migration belong to a separate change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The app/build.gradle section had a bare '@@' hunk header. GNU patch skips
such a hunk silently - exit 0, no "patching file" line, no .rej - so
check-patchfail called the patch clean while the
`implementation ComponentsDependencies.mozilla_appservices_suggest` line
never reached the tree on any base.
The section is now `@@ -545,6 +545,13 @@ dependencies {`, generated with
git diff against the tree as patched by every entry before it (no-adjust,
no-glean, no-gms, no-crashreporter, fenix-abi-split, branding,
update-check). Verified:
- check-patchfail --targets=android on 153.0esr: exit 0, build.gradle is
now patched, no fuzz;
- full common+android replay on 153.4.0esr: line lands (build.gradle:554),
fuzz 0, final sha256 33826457..., the value b567bb3 predicted;
- build.gradle-only replay of the 8 editors with suggest-data before each
of the other 7 and last: 33826457... in all 8 orders, so the seven
REVIEWED_ORDER_FREE rows still hold, now on bytes that land.
check-patch-order.py: notes updated; exit 0, 29/29 constraints.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A line starting with '@@' that is not '@@ -N[,M] +N[,M] @@[ heading]' is a hunk GNU patch 2.8 skips silently (exit 0, no .rej), so check-patchfail - which trusts patch's exit status - reports the patch clean while part of it never lands. That is how firefox-suggest-data's build.gradle dependency went missing from every build. The check is textual and runs over every patch in every list, whatever its scope; a hit is reported with file:line and exits 1 like a scope violation. $ python3 scripts/lint-patch-scope.py lint-patch-scope: OK - 120 patch file(s), no scope violations, no hunk header without line numbers Negative check (scratch copy with the pre-fix firefox-suggest-data.patch and a '@@ ' line appended to bootstrap-esr.patch): both reported, exit 1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
version.android 153.0esr -> 153.4.0esr (archive.mozilla.org's spelling;
153.4esr is a 404), release.android stays 1. `make help TARGETS=android`:
"in effect for this invocation : 153.4.0esr-1". Carries MFSA 2026-77,
-85, -93 and -100 (ESR 153.1-153.4, 201 CVEs).
check-patchfail --targets=android against the signed 153.4.0esr tarball
first exited 1 on three patches; each is fixed:
- android/ubo-readiness (ext-webRequest.js, 3/3 hunks): upstream removed
remoteTab/registerTraceableChannel from registerEvent and its
registrar. Ported: isLiveListener is now the 6th parameter,
convert(_fire) still marks the listener live, the registrar takes
{ fire, context } and passes !!context. test-ubo-readiness.js runs
18/18 against the patched tree once its call drops the old remoteTab
slot (follow-up; the unmodified test silently stops after 2).
- android/extension-update-controls (Preferences.cpp hunks 2 and 6):
upstream bug 2053962 added a backup-only standalone PWRunnable and
DispatchWriteComplete to fix the same coalescing bug our patch fixes
for every write. Our PWRunnable (each request owns its snapshot and
settles its own promise) replaces it; the change-line diff against
the old patch is exactly upstream's new backup code being removed.
- android/fix-canvas-extraction-permission-esr: 153.4.0esr carries the
fix (CaptureStream passes GetCurrentJSContext()). Deleted and dropped
from android.txt because Gecko fixed it; PATCH-SCOPE.md now 15/51/53/0
= 119.
Result: exit 0; 15 fuzzy hunks across 13 patches (14 across 12 on
153.0esr; the new one is session-cleanup's CookiePersistentStorage.cpp
include block, fuzz 2, left alone because its bytes are hash-pinned by
test-session-cleanup.py and evidence receipts); --fuzz=0 rejects 15
patches (14 before).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Appendix D records what §10 asks for, stage A only (no make dir, no Gecko build): the four ESR MFSAs and the nine Firefox-for-Android CVEs with no ESR counterpart (all open), the bump, the before/after check-patchfail numbers and every hand fix, which §6 pref checks ran (6a-6d: no pref of ours orphaned, drifted or newly mirror-once; 6e needs a built APK) and the eight gate outputs, all green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mullvad is discontinuing its DNS over HTTPS service. The 153 ESR beta listed "Mullvad (No Filtering)" in the Fenix DoH picker (privacy-defaults.patch), so a profile may still hold https://dns.mullvad.net/dns-query in pref_key_doh_provider_uri. When the service stops, Increased Protection loses DoH and Max Protection loses name resolution. New patches/android/doh-mullvad-migration.patch: - Core.engine calls DohProviderMigration.migrate before DefaultSettings reads dohProviderUrl. Once per profile, a stored provider on dns.mullvad.net, *.dns.mullvad.net or doh.mullvad.net becomes Settings.LIBREWOLF_DOH_PROVIDER_URI (dns10.quad9.net, also common.cfg's network.trr.uri). The mode is kept. The done flag sits in fenix_preferences next to the provider, so a Mullvad URI typed in later is left alone. - If the mode was Increased or Max, HomeActivity.onResume shows a one-time dialog naming the new provider. It uses the same AlertDialog mechanism as update-check. Off/Default: no dialog, the change is logged. - Mullvad is removed from the built-in catalog, which now matches common.cfg's doh-rollout.provider-list (settings 0cae8fb). DefaultDohSettingsProviderTest is updated to match. DohProviderMigrationTest adds 6 Robolectric cases. check-patch-order: privacy-defaults -> doh-mullvad-migration is declared; the reversed order rejects every DoH hunk. The seven HomeActivity.kt/Core.kt partners are recorded order-free: swapped full-tree replays give byte-identical files. On 153.4.0esr the patch applies at fuzz 0, offset 0. check-patchfail --targets=android passes, and the fuzz-0 run lists the same 15 rejects as before. lint-patch-scope passes (120), check-patch-order passes (30/30) and board --check-scope passes (15/53/52/0 = 120). Not compiled: there is no Gecko AAR here, so stage B builds it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mment doh-mullvad-migration.patch: DohProviderMigration.migrate now writes the replacement provider under pref_key_doh_provider_uri (the key Settings.dohProviderUrl reads) in the same SharedPreferences edit as the done and notice flags, so they really are committed together; the header said so before but the provider went through a separate apply(). migrate takes the Context to resolve that key. The notice no longer relies on a process-global noticeShowing flag that only OnDismissListener reset: the "already showing" check is a weak reference to the dialog compared with its owner activity, so a HomeActivity recreated under the dialog shows it again, and the pending flag is cleared only by the user (OK or cancel), not by a teardown dismissal. The about:config user-branch network.trr.uri case is documented as a known limitation. Three new Robolectric tests (one-edit atomicity, show once per activity / cleared by the user, recreation). The two lw/ files compile with kotlinc 2.3.20 -Werror against stubs of the Fenix types; the Fenix build and the test run remain stage B. test-ubo-readiness.js: drop the 153.0 remoteTab slot from registerEvent and the remoteTab context from convert(), matching the rebased ubo-readiness patch, and exit 1 unless all 18 tests finished. 18/18 on the patched 153.4.0esr tree; a test made to hang now fails with "7 of 18 ... a test never settled", and the stale null argument fails with "2 of 18". settings: Redoubt-settings 3db3803 rewords the app.releaseNotesURL comment, which cited support-destination.patch (not on this branch). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pass The 153.4.0esr unit-test run was the first to build these module test source sets. Each failed: - firefox-suggest-data: PinnedSuggestIngestionTest used mockk, which android-components excludes from every subproject, so :components:feature-fxsuggest test compilation failed. It now uses Mockito spy/doReturn and an argument captor. The assertions are the same. - extension-update-controls: AddonUpdaterWorkerTest used Mockito's ArgumentMatchers.eq on a Kotlin non-null String parameter. That eq returns null, which threw an NPE and leaked an unfinished verification into the next test. It now uses mozilla.components.support.test.eq. - global-privacy-controls: GeckoGlobalPrivacyControllerTest had a redundant `!!`, a warning that fails the build under -Werror. Targeted results: GeckoEngineTest 183/183, GeckoGlobalPrivacyControllerTest 5/5, AddonUpdaterWorkerTest 6/6, AddonManagerTest 30/30, PinnedSuggestIngestionTest 3/3, FxSuggestAdmissionTest 8/8 and OnlineSuggestionAdmissionTest 6/6. REBASE.md records these results, the Fenix suite result and the remaining failures in the Android Components modules. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Smoke suite, runtime pref audit, an E11 first-run capture with DNS 9.9.9.9 and a real Beta 2 -> 153.4 Mullvad DoH upgrade test, all run against the stage B x86_64 APK (unsigned sha256 59666c2a...). Beta 2 (rc-unsigned, 503bfd79...) is rerun in the same environment as a control. Both installed copies were signed with one throwaway key; the release key was not used. The Mullvad migration works: the dialog appears once, network.trr.uri becomes dns10.quad9.net, mode 3 is kept, and a fresh install shows no dialog. All five approved prefs read back at runtime. The pref audit exits 0. expected-prefs.txt is not regenerated, because its one stale row (librewolf.webgl.prompt) comes from LW-M7-14, not from this rebase. The smoke suite is not green. One defect is a 153.4 regression: about:config renders no rows, because the new baseline system CSP blocks config.xhtml's inline onload. Three defects also reproduce on Beta 2: uBO first-run readiness fails while AMO serves 1.75.0, a cold start to the home screen times out the uBO readiness gate, and the webgl harness expects EXPIRE_TIME where the patch writes EXPIRE_SESSION. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two Android Components test classes still asserted upstream behaviour that our patches change on purpose. The first 153.4.0esr run of their modules found them. - firefox-suggest-policy: in FxSuggestSuggestionProviderTest, includeSponsoredSuggestionsOnlyWhenAmpUnavailable and includeNonSponsoredSuggestionsOnlyWhenWikipediaUnavailable expected a storage query with providers = []. The patched provider admits no provider and so never queries the store. Both now verify storage.query is never called. - l10n-strings: AddonsManagerAdapterTest "bind blocklisted add-on" expected "violating Mozilla's policies". lw-brand rewrites that resource, so the test now reads it from R.string.mozac_feature_addons_status_blocklisted_1 and asserts that it no longer names Mozilla. This matches the existing Fenix test fixes. The hunks were generated against the pristine 153.4.0esr files, which no other patch touches. Run in the stage-B container: :components:feature-fxsuggest 73/73 and :components:feature-addons 218/218 pass. Before the change, 2 and 1 failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
board.py --check-fenix-tests warned on the full 153.4.0esr suite (615 classes / 5,562 tests): - SearchSuggestionsProvidersBuilderTest ran all 70 and passed. Its entry is removed. - AutofillSettingsMiddlewareTest failed 2 of its 7 tests, not 3. Its ceiling goes from 3 to 2. The gate's semantics allow both changes. A listed class that passes or fails below its ceiling is a warning meaning "trim". A class that is no longer listed and still passes cannot fail the gate. Re-run against the archived JUnit XML of that suite: # failing 22 = 19 environmental + 3 known-real + 0 unexpected ok: no failures beyond the documented allowlist (exit 0, no warnings) BUILD.md now states the current baseline: 19 environmental failures in 3 classes. The 2026-09-08 153.0esr figures are kept as history. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
§6e told the rebaser to confirm that librewolf.webgl.prompt compiled to false and treated true as the landmine. That has been wrong since canvas-webgl-permissions.patch (LW-M7-14, shipped in Beta 2). That patch removes the Android false override from webgl-prompt-default.patch because it ships the GeckoView/Fenix bridge that answers the prompt. A rebaser following the old text would "fix" a correct build. §6e now gives the expected value per patch list: true with LW-M7-14 listed, false without it. It treats a mismatch either way as a failure, because false with the bridge present leaves the bridge as dead code. Appendix D records the stage-B header: RelaxedAtomicBool true for .prompt and .hide in all three objdirs, which is the expected value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On 153.4.0esr this patch applied with offsets in nsFrameLoader.cpp and with fuzz 2 in the CookiePersistentStorage.cpp include block, where upstream added #include "mozilla/AppShutdown.h". b458dbc left it fuzzy because test-session-cleanup.py pinned its bytes. Those pins are now being re-captured for 153.4.0esr, and an exact --fuzz=0 replay is what the receipt checks. - nsFrameLoader.cpp: the two moved hunk headers shift by the reported offsets (+6, +8). - CookiePersistentStorage.cpp: the section is regenerated against the tree the patch meets on the Android stack (tarball plus every earlier common.txt/android.txt patch). Every +/- line is byte-identical to before. On the stack the refreshed patch applies with --fuzz=0 and no offsets. All 15 resulting files are byte-identical to the stage-B tree, which was patched with the old, fuzzy version and then built and run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test-extension-update-controls.py, test-global-privacy-controls.py and test-session-cleanup.py pinned the 153.0esr source and 153.0esr patch bytes. The rebase changed extension-update-controls.patch and global-privacy-controls.patch, so all three failed on a digest check before they reached any source check. evidence/lw-m7-01/esr-153.4.0/receipts/recapture.py rebuilds each patch's before tree from the signed 153.4.0esr tarball plus every earlier common.txt/android.txt patch, in check-patchfail order. That is the real tree state the patch meets, which the 153.0esr guest and scoped-pristine captures stood in for. It then requires an exact --fuzz=0 replay and compares the whole-stack result with the stage-B build tree: extension-update-controls 19/27 before files exact 27/27 = stage B global-privacy-controls 9/21 before files exact 21/21 = stage B session-cleanup 13/15 before files exact 15/15 = stage B The present/absent counts and predecessor sets match the 153.0esr receipts. Running it twice gives byte-identical output. replay.py verifies a receipt from repository files alone. Each test now uses it when evidence/lw-m7-01/esr-<version.android>/receipts exists and otherwise falls back to its original 153.0esr chain, which is left untouched. Every downstream source check still runs on the replayed tree: Preferences.cpp markers, JS/JSON/TOML/XML, the 18 extension-update and 18 global-privacy JS host tests, the XPIDL/WebIDL parse, and the test inventories. Not re-captured: there is no guest capture for 153.4.0esr, and the pinned XPIDL/WebIDL parser sources are still 153.0esr's. The task-local tools lw-m7-35/36/37 check-ordering.py and lw-m7-36 check-source.py remain 153.0esr-only and fail on the new patch bytes, as they already did at d2d0840. README.md in the receipts directory says what each file proves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cute -n never enters the source tree. Every other existence check prints "# skipped under --no-execute: ..." for that reason. The brand-image step added in 19dbe98 did not. It looked up its 82 destinations in whatever directory -n was run from, so a dry run exited 1 on "LW-M4-07 expects 82 Firefox brand file(s) that are not in the tree". With a tree in the cwd it would have copied for real. Under --no-execute it now prints what it skipped and returns before the check and the copy. A real run is unchanged: it checks every destination first and writes nothing if any is missing (landmine L4). scripts/tests/test-ubo-extension.py: 22/22 (was 21/22, the android dry-run subtest exiting 1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The default --apk/--apksigner directory was hardcoded to librewolf-android-apk-153.0esr-1-unsigned/apk. It is now the Makefile's ANDROID_APK_OUTDIR for the current track, librewolf-android-apk-<version.android>-<release.android>/apk, so a rebase moves it too. An absent input is still a usage error, not a pass. The android-apk.sh output does not contain apksigner.jar; the 153.0esr signing handoff bundle did. So with no arguments, --apksigner usually needs to be given. With the stage-B 153.4.0esr x86_64 APK and the apksigner.jar from the 153.0esr signing handoff bundle: 29/29 pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Closes the "Left open" items that this pass resolved: - receipts re-captured for all three pinned tests; - stage B done, L1 header true as §6e expects; - Fenix allowlist trimmed; - the two AC test classes now assert Redoubt's behaviour. Adds the post-refresh fuzz row (14 hunks / 12 patches, 14 rejects at --fuzz=0) and the gate results from re-running everything on the 153.4.0esr tree. scripts/tests (15 .py + 8 .js) all exit 0, and every board.py gate, lint-patch-scope, check-patch-order and check-patchfail --targets=android exit 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…not 2
The patch writes EXPIRE_NEVER for Remember in normal browsing and
EXPIRE_SESSION otherwise, matching LW-M7-14 ("real engine session expiry",
"expire on normal process restart") and desktop webgl-permission-desktop.
nsIPermissionManager.idl has EXPIRE_SESSION=1; 2 is EXPIRE_TIME. The 2
came from the LW-M7-14 node mock, which defined EXPIRE_SESSION: 2, and was
copied into the smoke's wait_record and CanvasPermissionTest's private
assertion. Fix both expectations; the patch's runtime code is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…baseline CSP 153.4.0esr's Document::InitCSP appends the baseline system CSP (script-src chrome: resource: moz-src:) to system-principal documents. GeckoView's about:config (config.xhtml) still wires itself up with inline on* attributes on ESR, so script-src-attr blocks all 13 of them -- including body onload, so the page never initialises (runtime diag new-153.4-aboutconfig-csp.json). Mozilla already fixed this: config.xhtml/config.js in firefox-153.0.4 and firefox-157.0 are byte-identical and move every handler into config.js via addEventListener. The new hunks are exactly diff -u 153.4.0esr -> 157.0 of those two files; the patched result matches upstream's md5s. The page is not exempted from the CSP. Applies at --fuzz=0 on pristine 153.4.0esr. Needs a Gecko rebuild (omni.ja). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ld starts Two "uBlock Origin setup failed" defects, both in published Beta 2. Launcher cold start: on APP_STARTUP Gecko delays persistent background pages until the first GeckoView window sends extensions-late-startup. The session middleware holds every tab until uBO is ready, and a launcher start (home screen, no URL) opens no window, so the blocking listener can never register and the 30 s timeout always fires. A VIEW intent worked only because IntentReceiverActivity opens a speculative session. The preinstaller now does the same before it waits: it opens a window, loads nothing, and the first tab adopts it. AMO update during first run: AddonUpdaterWorker runs as soon as uBO is installed and replaces it with a newer signed AMO release. That shutdown rejects the version-bound wait. After a failed wait the preinstaller re-reads the registry for up to 5 s. Only a same-ID copy that is enabled and strictly newer than the awaited version restarts the attempt, with a fresh timeout and at most twice. It takes the existing-installation path, so there is no reinstall. Absence, disablement, the same version, a downgrade or an unparseable version keeps the failure. Gecko still enforces the signature, and the readiness signal is still the exact version's live blocking listener. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AMO serves 1.75.0, so on first run every 1.74.0 install was immediately auto-updated under the readiness wait. Checks on the new pin (AMO file 5034826, 4650100 bytes, sha256 5b744158...): - fetch-ubo-extension.py validation; - three independent downloads with the same digest; - PKCS#7 chain to the 153.4 tree's AMO production root; - JAR digests over every member; - the same permissions and Android minimum as 1.74.0. js/start.js and js/traffic.js are byte-identical to 1.74.0, so the listener-after-filters property in ubo-readiness.patch still holds. Only that patch's header comment changes; its diff and Gecko are untouched. The LW-M7-34 update-fixture pair moves to 1.74.0 -> 1.75.0, because its verifier binds the newer fixture to the packaged pin. The 1.75.0 original and its receipts were fetched with fixtures.py --fetch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pped Every device check opens a URL first, because Marionette needs a Gecko window, and that VIEW intent's speculative session is exactly what released Gecko's delayed extension startup. So the harness could never see the 30 s uBO failure dialog that Beta 2 shows on every launcher cold start. The new check resolves the launcher activity through the package manager. It cold-starts it on a fresh profile and again on a restart, and waits past the 30 s timeout. It fails on the dialog, on a logged failure, or on a missing positive readiness line, because silence is not readiness. Device evidence for both uBO fixes is in docs/android/evidence/lw-m3-07/esr-153.4-ubo-startup-20261002/: - the pre-fix APK fails the check; - the fixed APK passes it, plus first-navigation blocking with a signed 1.75.0; - a variant pinned to 1.74.0 survives a real AMO update during first run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rofile Rebuild from the committed tree: a fresh `make dir TARGETS=android` at 0a13444, all three ABIs from new objdirs with MOZ_BUILD_DATE pinned to 20261002044800, the fat AAR, and the R8 release APKs (unsigned). The x86_64 APK (1ac3b01d..., throwaway-signed 77348e7d...) ran on a fresh emulator with AMO reachable, no priming and no iptables. The stage C product defects are fixed on device: - about:config renders and keeps an edit across a restart - launcher cold starts reach uBO readiness, with no dialog - uBO 1.75.0 is pinned and AMO has nothing newer, so there is no update race The pref audit exits 0 and the generator differs only in the librewolf.webgl.prompt row. The Beta 2 -> rc2 Mullvad upgrade migrates once to Quad9 with mode 3 kept, and no uBO dialog stacks on the DoH dialog. The smoke suite is not green. webgl hits a harness selector that clicks by text where the Compose tab menu has only content-desc. search and no-suggest are blocked by the first-run uBO sheet. no-suggest also counts uBO's 37 s post-launch list updater as typing traffic. With the selector worked around in an uncommitted diagnostic copy, the quiet "Review" action in a private tab opened nothing in 3 of 3 runs, and the cause is not established. The README records each of these. Stage C README: cite run2/16 for the second-launch logcat (25-* is empty), and note that its APK predates later patch-byte changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uggest Harness defect A (graphics): Fenix's Compose tab-counter menu exposes "New private tab" only as content-desc (PopupToMenuItemsMapper.kt clears semantics), so tab_menu() clicking text="New private tab" never matched. menu_item() now selects by text or content-desc, counts one node carrying both once, and refuses two different matching nodes. Harness defect B (check-search, check-no-suggest): on a fresh profile the "uBlock Origin was added" sheet covers the toolbar. Both checks now go through toolbar_ready(), which acknowledges the sheet with the graphics harness's own ubo_added_notice() (loaded from scripts/, not copied) and accepts the address bar only after two matching dumps with no sheet. ubo_added_notice_present() is shared for the read-only close wait. check-no-suggest typing window: the check restarts the app, and uBO's asset updater runs autoUpdateDelayAfterLaunch (37 s) after every launch, fetching one stale list per autoUpdateAssetFetchPeriod (5 s). Both values are now read from the APK's bundled xpi, and typing starts only once the launch timer must have fired and the capture has carried no non-background outbound payload for max(20 s, 3 fetch periods). No host is exempted: the pre-typing traffic is recorded as evidence and the typing window is judged exactly as before. A capture that never goes quiet (300 s) is reported in the failure detail rather than hidden. Offline tests only; no emulator run in this commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… keyboard The quiet "Review" action in a private tab opened nothing in 3 of 3 rc2 runs. It is not a product defect. A New (private) tab opened from the tab-counter menu leaves the soft keyboard on screen after the URL is submitted. The keyboard window stays visible and touchable over [0,1145][1080,1920] in the input dispatcher, while InputMethodManager reports mInputShown=false. uiautomator dumps only the app window, so the harness saw the snackbar and tapped Review at 946,1805. The tap landed on a key (VibratorService logged a TOUCH vibration from the IME's uid), so Fenix never received it. A scratch build with logging confirmed that the snackbar's action listener never ran. Review opened the dialog in private tabs once the keyboard was out of the way, and so did the site-information path. - tap() reads `dumpsys input` and refuses to tap through any foreign window. A soft keyboard is closed first; anything else is a Failure. - type_url() closes the keyboard after submitting. It allows 1.5 s for the normal hide, then force-stops the default IME (never the app) and records soft-keyboard-closed in evidence. - The quiet snackbar is LENGTH_LONG and can expire between the dump and the tap: rc2 had one normal-tab miss, and the first diagnostic run here had another. A miss now falls back to the site controls only if the notice is gone and no other permission UI opened. run() still requires Review to open the list in a normal tab and in a private tab. - After "Close tab" closes the last private tab, Fenix shows the empty private home, whose tab-counter menu has no "New private tab". The second private page is typed into that home's address bar, which is what a user would do there. The harness had never reached this step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…yboard The quiet "Review" action works in private tabs. The rc2 harness tapped it through a soft keyboard that stayed over the bottom of the screen after the private URL was typed. uiautomator cannot see that window. - Diagnosis: a scratch build with logging only shows that the action listener never runs for that tap. dumpsys input shows the IME window visible and touchable while IMMS reports it hidden, and the IME's uid takes the touch. - The keyboard behaviour does not depend on private mode or on LW-M7-14. A normal tab from the same menu, a plain page and Beta 2 all show it. A URL typed into the home screen's address bar does not. - With the keyboard closed, Review opens the dialog in private tabs: rc2 3/3 and Beta 2 1/1 in manual reproduction, and the harness runs below 6/6. - With the committed harness (f7f519f) on the rc2 APK and a fresh profile per run, the graphics acceptance passes 3/3 (161 checks each). Every run records the harness hashes, HEAD and a clean tree. - Gates on this tree pass: check-patchfail android, lint-patch-scope, check-patch-order, board.py --check and --check-scope. There is no rc3 because the product is unchanged. The stuck keyboard after the tab-counter menu's New (private) tab is recorded for separate triage, starting with upstream Fenix 153. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…M7-14 mock Reran every device check on the rc2 APK (77348e7d...af83, throwaway-signed), one fresh profile per check, with the harness committed at 11fd562 (android-smoke.sh aabbb7a7..., android-graphics-smoke.py ce0072ea...). There is no rc3, because the product did not change after rc2. - 14 checks PASS. These include the full graphics acceptance (161 checks, private grants, frames, lifetimes), which passed twice, plus check-search, launcher-start, aboutconfig, the three uBO checks, self-test and strings. - On about:config, the console service shows 0 CSP / script-src-attr errors, and a positive control proves the query sees them. Logcat does not carry console errors on this release build, as the probe shows. - The negative control behaves as expected: Beta 2 fails --check-launcher-start. - first-run-capture and check-no-remote-settings are red, as expected (E12). - check-no-suggest FAILs. The red packets are 39/46-byte, keep-alive-sized records on connections opened before typing. No new connection, DNS query or QUIC packet was sent before Enter. The harness was not changed. LW-M7-14 evidence: the Services.perms double now has EXPIRE_SESSION 1, the real nsIPermissionManager value, and the literal asserts and fixture seeds now match it. The .tap was regenerated against the rc2 tree and is still 37/37. No shipped byte changes. The stale "pinned uBO 1.74.0" comment in ubo-readiness.patch is left alone. It is packed into omni.ja, so fixing it needs a Gecko rebuild. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rc2's final acceptance failed check-no-suggest on 13 non-background packets (504 B) that were all HTTP/2 keep-alive or close records on TLS connections opened before typing (AMO, uBO list hosts; ~59 s ping period). The rule counted every outbound payload byte in the window. attribute_typing_flows() now reads the capture from its header to the end of the window, in both directions, and gives every flow with an outbound SYN, datagram or payload in the window a verdict. It is typing traffic when any of these hold: a DNS query (53/853), a SYN inside the window, a flow first seen inside the window, any non-background UDP (QUIC included), an address resolved by a DNS answer inside the window, an SNI that is a configured search/suggestion host, or an outbound segment that is not ONE TLS application-data/alert record of at most 46 B. 46 B is one 17-byte HTTP/2 control frame (9-byte header + 8-byte PING/GOAWAY payload) in the larger of the TLS envelopes: 1.3 adds 22 B (39 B on the wire), 1.2 AES-GCM adds 29 B (46 B). rc2's records were exactly 39/46 B pings and 24/31 B alerts. Background exemptions are the existing SNI/DNS-name ones, unchanged. Every non-background payload pcap_payloads sees must also sit on a passing flow. The per-flow attribution is recorded in the check JSON (typing_flow_attribution). Re-graded offline against rc2's own capture, the 10 flows of that window are 7 keepalive + 3 background, and the post-Enter window flags the noai.duckduckgo.com DNS query and connections. --no-suggest-negative-control turns "Show search suggestions" ON through Settings before typing; the check must then FAIL, the detail names the suggestion host, and the switch is restored OFF. 16 new offline tests on synthetic captures (81 total). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The PASS detail still described the old byte rule ("no outbound
transport payload outside background flows"). It now states the
per-connection rule and counts the keep-alive and background flows it
let through.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hics UI guards Documents what c35662c, f7f519f and the connection attribution changed and never wrote down: the uBO installed-notice handling shared with check-search, the pre-typing quiet wait derived from the bundled uBO's updater schedule, per-connection attribution with the derivation of the 46 B keep-alive bound, the --no-suggest-negative-control flag, and, for graphics acceptance, the input-dispatcher tap guard, the default-IME force-close, and the Review-expiry fallback together with the requirement that Review opened the list in both a normal and a private tab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…trol fails on ac.duckduckgo.com Device runs of --check-no-suggest on the rc2 APK (installed 77348e7d…af83, throwaway key) with the committed harness dba0f279 (86a8fd0), on one emulator, DNS 9.9.9.9, fresh profile each run, AMO reachable, no priming or iptables: - negative control (--no-suggest-negative-control, suggestions ON before typing): FAIL as required. 3 new TLS connections to ac.duckduckgo.com plus its udp/53 query, and 2 DoT lookups. In the same window the 7 pre-existing AMO/uBO flows were graded keepalive. - three normal runs: PASS, each with 7 keepalive + 3 background flows and 0 typing flows. Under the old byte rule each would have failed on 13 packets / 504 B, the same as rc2's row 8. - row 8's own capture, re-graded offline with the new attribution: 0 typing flows. The final-acceptance README now says that row 8 had 16 payload packets, 3 of them background and 13 failing (it had said 13 in one place and 16 in another). It adds rows 8a-8d with the new harness hash, and the unit test results (test-android-smoke.py: 81 OK). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owner signed rc2's four APKs on the Fedora host under a dated, candidate-specific exception. Each signed APK is byte-identical, entry for entry, to its tested unsigned input, and all four pass the published-fingerprint v2+v3 check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every asset re-downloaded from the public prerelease matches SHA256SUMS.signed and passes the published-fingerprint v2+v3 check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #1 (base
desktop/firefox-157). Merge #1 first, then retarget this PR tomain.What changes for Android
fix-canvas-extraction-permission).about:configshowed only a spinner. 153.4's baseline CSP for system pages blocked the page's inline handlers, so this backports upstream's own fix, which moves them into the script. The CSP is not weakened.firefox-suggest-data.patchhad a@@hunk header with no line numbers, so GNU patch skipped it without a word. A new lint rejects such headers.Verified
check-patchfail(android on 153.4.0esr, desktop unchanged),lint-patch-scope,check-patch-order(CI's failing step, now 30/30),board.pychecks. The full Fenix unit suite gives 0 unexpected failures (E5), and three Android Components tests from our patches that had never compiled were fixed.about:configwith 0 CSP errors, the uBO checks, andno-suggest(3/3, with a suggestions-ON negative control that catchesac.duckduckgo.com). The pref audit exits 0.docs/android/evidence/lw-m7-01/esr-153.4.0/anddocs/android/REBASE.mdAppendix D.Owner decisions still open
network.lna.block_insecure_contexts: upstream changed it to false in 153.4. Should Redoubt set it?dns10.quad9.net).expected-prefs.txtstill sayslibrewolf.webgl.prompt=false, while it has shippedtruesince LW-M7-14. It was left unregenerated on purpose.🤖 Generated with Claude Code