morgan pushed to branch tor-browser-140.5.0esr-15.0-1 at The Tor Project / Applications / Tor Browser Commits: e891f9c2 by Henry Wilkes at 2025-11-05T14:14:01+00:00 fixup! TB 7494: Create local home page for TBB. TB 44314: Delay initial data for preloaded about:tor pages. - - - - - 4 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 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; View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/e891f9c2... -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/e891f9c2... You're receiving this email because of your account on gitlab.torproject.org.
participants (1)
-
morgan (@morgan)