Loading browser/components/abouttor/AboutTorChild.sys.mjs +18 −5 Original line number Diff line number Diff line Loading @@ -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": Loading @@ -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") Loading @@ -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 +61 −18 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -21,24 +23,42 @@ export class AboutTorParent extends JSWindowActorParent { */ static #dismissYEC = false; didDestroy() { initializedActors.delete(this); } /** * Whether this instance has a preloaded browser. * * @type {boolean} */ #preloaded = false; 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); /** * 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 Promise.resolve({ return { torConnectEnabled: lazy.TorConnect.enabled, messageData: lazy.AboutTorMessage.getNext(), isStable: AppConstants.MOZ_UPDATE_CHANNEL === "release", Loading @@ -49,7 +69,30 @@ export class AboutTorParent extends JSWindowActorParent { ), appLocale, dismissYEC: AboutTorParent.#dismissYEC, }); }; } didDestroy() { initializedActors.delete(this); } receiveMessage(message) { switch (message.name) { case "AboutTor:GetInitialData": { // Track this actor to send future updates. initializedActors.add(this); 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(this.#getInitialData()); } case "AboutTor:SetSearchOnionize": Services.prefs.setBoolPref(onionizePref, message.data); Loading browser/components/abouttor/content/aboutTor.js +26 −12 Original line number Diff line number Diff line Loading @@ -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 => { Loading @@ -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", () => { Loading browser/components/tabbrowser/NewTabPagePreloading.sys.mjs +18 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading
browser/components/abouttor/AboutTorChild.sys.mjs +18 −5 Original line number Diff line number Diff line Loading @@ -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": Loading @@ -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") Loading @@ -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 +61 −18 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -21,24 +23,42 @@ export class AboutTorParent extends JSWindowActorParent { */ static #dismissYEC = false; didDestroy() { initializedActors.delete(this); } /** * Whether this instance has a preloaded browser. * * @type {boolean} */ #preloaded = false; 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); /** * 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 Promise.resolve({ return { torConnectEnabled: lazy.TorConnect.enabled, messageData: lazy.AboutTorMessage.getNext(), isStable: AppConstants.MOZ_UPDATE_CHANNEL === "release", Loading @@ -49,7 +69,30 @@ export class AboutTorParent extends JSWindowActorParent { ), appLocale, dismissYEC: AboutTorParent.#dismissYEC, }); }; } didDestroy() { initializedActors.delete(this); } receiveMessage(message) { switch (message.name) { case "AboutTor:GetInitialData": { // Track this actor to send future updates. initializedActors.add(this); 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(this.#getInitialData()); } case "AboutTor:SetSearchOnionize": Services.prefs.setBoolPref(onionizePref, message.data); Loading
browser/components/abouttor/content/aboutTor.js +26 −12 Original line number Diff line number Diff line Loading @@ -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 => { Loading @@ -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", () => { Loading
browser/components/tabbrowser/NewTabPagePreloading.sys.mjs +18 −0 Original line number Diff line number Diff line Loading @@ -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; Loading