Pier Angelo Vendrame pushed to branch tor-browser-145.0a1-16.0-1 at The Tor Project / Applications / Tor Browser Commits: 57842b65 by Henry Wilkes at 2025-11-20T17:47:36+01:00 fixup! TB 7494: Create local home page for TBB. TB 44314: Delay initial data for preloaded about:tor pages. - - - - - 7fe873d8 by Pier Angelo Vendrame at 2025-11-20T17:47:37+01:00 fixup! BB 43140: Tighten up fonts on Linux. BB 44315: Fix the fonts on the updater. - - - - - 5079b9ac by Pier Angelo Vendrame at 2025-11-20T17:47:38+01:00 fixup! BB 43525: Skip Remote Settings for search engine customization. MB 483: Ship DDG without AI as a bundled search engine. MB 487: Use custom order for search engines. - - - - - f940028c by Pier Angelo Vendrame at 2025-11-20T17:47:38+01:00 fixup! TB 42891: Set the bundled search engine for Tor Browser. MB 487: Use custom order for search engines. - - - - - 81b52668 by Beatriz Rizental at 2025-11-20T17:47:39+01:00 fixup! Tweaks to the build system Skip downloading WPT artifacts when generating test artifacts. - - - - - 851147b1 by clairehurst at 2025-11-20T17:47:40+01:00 fixup! [android] Disable features and functionality - - - - - 10 changed files: - browser/components/abouttor/AboutTorChild.sys.mjs - browser/components/abouttor/AboutTorParent.sys.mjs - browser/components/abouttor/content/aboutTor.js - browser/components/tabbrowser/NewTabPagePreloading.sys.mjs - mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt - testing/testsuite-targets.mk - toolkit/components/search/content/base-browser-search-engine-icons.json - toolkit/components/search/content/base-browser-search-engines.json - toolkit/components/search/tests/xpcshell/test_base_browser.js - toolkit/mozapps/update/updater/updater.cpp Changes: ===================================== browser/components/abouttor/AboutTorChild.sys.mjs ===================================== @@ -6,11 +6,9 @@ export class AboutTorChild extends JSWindowActorChild { switch (event.type) { case "DOMContentLoaded": this.sendQuery("AboutTor:GetInitialData").then(data => { - const initialDataEvent = new this.contentWindow.CustomEvent( - "InitialData", - { detail: Cu.cloneInto(data, this.contentWindow) } - ); - this.contentWindow.dispatchEvent(initialDataEvent); + if (data) { + this.#dispatchInitialData(data); + } }); break; case "SubmitSearchOnionize": @@ -36,6 +34,9 @@ export class AboutTorChild extends JSWindowActorChild { receiveMessage(message) { switch (message.name) { + case "AboutTor:DelayedInitialData": + this.#dispatchInitialData(message.data); + break; case "AboutTor:DismissYEC": { this.contentWindow.dispatchEvent( new this.contentWindow.CustomEvent("DismissYEC") @@ -45,4 +46,16 @@ export class AboutTorChild extends JSWindowActorChild { } return undefined; } + + /** + * Send the initial data to the page. + * + * @param {object} data - The data to send. + */ + #dispatchInitialData(data) { + const initialDataEvent = new this.contentWindow.CustomEvent("InitialData", { + detail: Cu.cloneInto(data, this.contentWindow), + }); + this.contentWindow.dispatchEvent(initialDataEvent); + } } ===================================== browser/components/abouttor/AboutTorParent.sys.mjs ===================================== @@ -8,6 +8,8 @@ ChromeUtils.defineESModuleGetters(lazy, { }); const initializedActors = new Set(); +const onionizePref = "torbrowser.homepage.search.onionize"; +const surveyDismissVersionPref = "torbrowser.homepage.survey.dismiss_version"; /** * Actor parent class for the about:tor page. @@ -21,35 +23,76 @@ export class AboutTorParent extends JSWindowActorParent { */ static #dismissYEC = false; + /** + * Whether this instance has a preloaded browser. + * + * @type {boolean} + */ + #preloaded = false; + + /** + * Method to be called when the browser corresponding to this actor has its + * preloadedState attribute removed. + */ + preloadedRemoved() { + if (!this.#preloaded) { + return; + } + this.#preloaded = false; + // Send in the initial data now that the page is actually going to be + // visible. + this.sendAsyncMessage( + "AboutTor:DelayedInitialData", + this.#getInitialData() + ); + } + + /** + * Get the initial data for the page when it is about to be shown. + * + * @returns {object} - The initial data. + */ + #getInitialData() { + let appLocale = Services.locale.appLocaleAsBCP47; + if (appLocale === "ja-JP-macos") { + appLocale = "ja"; + } + + return { + torConnectEnabled: lazy.TorConnect.enabled, + messageData: lazy.AboutTorMessage.getNext(), + isStable: AppConstants.MOZ_UPDATE_CHANNEL === "release", + searchOnionize: Services.prefs.getBoolPref(onionizePref, false), + surveyDismissVersion: Services.prefs.getIntPref( + surveyDismissVersionPref, + 0 + ), + appLocale, + dismissYEC: AboutTorParent.#dismissYEC, + }; + } + didDestroy() { initializedActors.delete(this); } receiveMessage(message) { - const onionizePref = "torbrowser.homepage.search.onionize"; - const surveyDismissVersionPref = - "torbrowser.homepage.survey.dismiss_version"; switch (message.name) { case "AboutTor:GetInitialData": { // Track this actor to send future updates. initializedActors.add(this); - let appLocale = Services.locale.appLocaleAsBCP47; - if (appLocale === "ja-JP-macos") { - appLocale = "ja"; + const browser = this.browsingContext.top.embedderElement; + if (browser?.getAttribute("preloadedState") === "preloaded") { + // Wait until the page is actually about to be shown before sending + // the initial data. + // Otherwise the preloaded page might receive data that has expired by + // the time the page is shown. And it will iterate + // AboutTorMessage.getNext too early. See tor-browser#44314. + this.#preloaded = true; + return Promise.resolve(null); } - return Promise.resolve({ - torConnectEnabled: lazy.TorConnect.enabled, - messageData: lazy.AboutTorMessage.getNext(), - isStable: AppConstants.MOZ_UPDATE_CHANNEL === "release", - searchOnionize: Services.prefs.getBoolPref(onionizePref, false), - surveyDismissVersion: Services.prefs.getIntPref( - surveyDismissVersionPref, - 0 - ), - appLocale, - dismissYEC: AboutTorParent.#dismissYEC, - }); + return Promise.resolve(this.#getInitialData()); } case "AboutTor:SetSearchOnionize": Services.prefs.setBoolPref(onionizePref, message.data); ===================================== browser/components/abouttor/content/aboutTor.js ===================================== @@ -562,11 +562,35 @@ const YecArea = { }, }; +let gInitialData = false; +let gLoaded = false; + +function maybeComplete() { + if (!gInitialData || !gLoaded) { + return; + } + // Wait to show the content when the l10n population has completed. + if (document.hasPendingL10nMutations) { + window.addEventListener( + "L10nMutationsFinished", + () => { + document.body.classList.add("initialized"); + }, + { once: true } + ); + } else { + document.body.classList.add("initialized"); + } +} + window.addEventListener("DOMContentLoaded", () => { SearchWidget.init(); MessageArea.init(); SurveyArea.init(); YecArea.init(); + + gLoaded = true; + maybeComplete(); }); window.addEventListener("InitialData", event => { @@ -584,18 +608,8 @@ window.addEventListener("InitialData", event => { SurveyArea.potentiallyShow(surveyDismissVersion, isStable, appLocale); YecArea.potentiallyShow(dismissYEC, isStable, appLocale); - // Wait to show the content when the l10n population has completed. - if (document.hasPendingL10nMutations) { - window.addEventListener( - "L10nMutationsFinished", - () => { - document.body.classList.add("initialized"); - }, - { once: true } - ); - } else { - document.body.classList.add("initialized"); - } + gInitialData = true; + maybeComplete(); }); window.addEventListener("DismissYEC", () => { ===================================== browser/components/tabbrowser/NewTabPagePreloading.sys.mjs ===================================== @@ -178,6 +178,24 @@ export let NewTabPagePreloading = { this.browserCounts[countKey]--; browser.removeAttribute("preloadedState"); browser.setAttribute("autocompletepopup", "PopupAutoComplete"); + // Let a preloaded about:tor page know that it is no longer preloaded + // (about to be shown). See tor-browser#44314. + // NOTE: We call the AboutTorParent instance directly because it is not + // reliable for the AboutTorParent to wait for the "preloadedState" + // attribute to change via a MutationObserver on the browsingContext's + // browser element because the AboutTorParent's browsingContext's browser + // element may be swapped out. E.g. see the "SwapDocShells" event. + // NOTE: We assume that this is the only place that removes the + // "preloadedState" attribute. + // NOTE: Alternatively, we could have the AboutTorParent wait for + // MozAfterPaint, but this would be slightly delayed. + try { + browser.browsingContext?.currentWindowGlobal + ?.getActor("AboutTor") + .preloadedRemoved(); + } catch { + // Not an about:tor page with an AboutTorParent instance. + } } return browser; ===================================== mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt ===================================== @@ -203,11 +203,9 @@ open class DefaultToolbarMenu( */ @VisibleForTesting(otherwise = PRIVATE) fun shouldShowTranslations(): Boolean { - val isEngineSupported = store.state.translationEngine.isEngineSupported - return selectedSession?.let { - isEngineSupported == true && - FxNimbus.features.translations.value().mainFlowBrowserMenuEnabled - } ?: false + // We need this because in FxNimbus.kt, mainFlowToolbarEnabled defaults to true + // ```mainFlowToolbarEnabled: Boolean = true``` + return false // bug_44304 Hide broken translat page action. } /** ===================================== testing/testsuite-targets.mk ===================================== @@ -151,7 +151,7 @@ download-wpt-manifest: $(call py_action,download_wpt_manifest) define package_archive -package-tests-$(1): stage-all package-tests-prepare-dest download-wpt-manifest +package-tests-$(1): stage-all package-tests-prepare-dest $$(call py_action,test_archive, \ $(1) \ '$$(abspath $$(test_archive_dir))/$$(PKG_BASENAME).$(1).tests.$(2)') ===================================== toolkit/components/search/content/base-browser-search-engine-icons.json ===================================== @@ -2,6 +2,9 @@ "ddg": [ { "url": "chrome://global/content/search/duckduckgo.ico", "imageSize": 32 } ], + "ddg-noai": [ + { "url": "chrome://global/content/search/duckduckgo.ico", "imageSize": 32 } + ], "ddg-onion": [ { "url": "chrome://global/content/search/duckduckgo.ico", "imageSize": 32 } ], ===================================== toolkit/components/search/content/base-browser-search-engines.json ===================================== @@ -17,6 +17,24 @@ "recordType": "engine", "variants": [{ "environment": { "allRegionsAndLocales": true } }] }, + { + "base": { + "aliases": ["ddgnoai"], + "classification": "general", + "name": "DuckDuckGo (no AI)", + "urls": { + "search": { + "base": "https://noai.duckduckgo.com/", + "params": [], + "searchTermParamName": "q" + } + } + }, + "id": "91687f02-56dd-4fef-ba26-bf139dff3166", + "identifier": "ddg-noai", + "recordType": "engine", + "variants": [{ "environment": { "allRegionsAndLocales": true } }] + }, { "base": { "aliases": ["ddgonion"], @@ -93,5 +111,21 @@ "recordType": "defaultEngines", "globalDefault": "ddg", "globalDefaultPrivate": "ddg" + }, + { + "recordType": "engineOrders", + "orders": [ + { + "environment": { "allRegionsAndLocales": true }, + "order": [ + "ddg", + "ddg-noai", + "ddg-onion", + "startpage", + "startpage-onion", + "wikipedia" + ] + } + ] } ] ===================================== toolkit/components/search/tests/xpcshell/test_base_browser.js ===================================== @@ -4,12 +4,15 @@ /** * This tests the SearchService to check our override of the remote settings is * working as expected. + * + * When adding new engines, it should be enough to change expectedURLs below. */ "use strict"; const expectedURLs = { ddg: "https://duckduckgo.com/?q=test", + "ddg-noai": "https://noai.duckduckgo.com/?q=test", "ddg-onion": "https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion/?q=te...", startpage: "https://www.startpage.com/sp/search?q=test", @@ -50,3 +53,11 @@ add_task(function test_checkSearchURLs() { Assert.equal(foundUrl, url, `The URL of ${engine.name} is not altered.`); } }); + +add_task(async function test_iconsDoesNotFail() { + for (const id of Object.keys(expectedURLs)) { + const engine = Services.search.getEngineById(id); + // No need to assert anything, as in case of error this method should throw. + await engine.getIconURL(); + } +}); ===================================== toolkit/mozapps/update/updater/updater.cpp ===================================== @@ -3474,6 +3474,10 @@ int NS_main(int argc, NS_tchar** argv) { putenv(const_cast<char*>("MOZ_USING_SERVICE=")); #endif +#if defined(XP_UNIX) && !defined(XP_MACOSX) + unsetenv("FONTCONFIG_PATH"); +#endif + if (argc == 2 && NS_tstrcmp(argv[1], NS_T("--channels-allowed")) == 0) { #ifdef MOZ_VERIFY_MAR_SIGNATURE int rv = PopulategMARStrings(); View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/4e33816... -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/4e33816... You're receiving this email because of your account on gitlab.torproject.org.