Loading browser/components/torconnect/TorConnectParent.sys.mjs +22 −3 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ import { TorStrings } from "moz-src:///toolkit/modules/TorStrings.sys.mjs"; import { TorConnect, TorConnectStage, TorConnectTopics, } from "moz-src:///toolkit/modules/TorConnect.sys.mjs"; Loading @@ -26,9 +27,7 @@ and a particular about:torconnect page * It adapts and relays the messages from and to the TorConnect module. */ export class TorConnectParent extends JSWindowActorParent { constructor(...args) { super(...args); actorCreated() { const self = this; // JSWindowActiveParent derived objects cannot observe directly, so create a Loading @@ -44,6 +43,9 @@ export class TorConnectParent extends JSWindowActorParent { case TorConnectTopics.StageChange: self.sendAsyncMessage("torconnect:stage-change", obj); break; case TorConnectTopics.ProviderStatusChange: self.sendAsyncMessage("torconnect:provider-status-change", obj); break; case TorConnectTopics.BootstrapProgress: self.sendAsyncMessage("torconnect:bootstrap-progress", obj); break; Loading @@ -64,6 +66,10 @@ export class TorConnectParent extends JSWindowActorParent { this.torConnectObserver, TorConnectTopics.StageChange ); Services.obs.addObserver( this.torConnectObserver, TorConnectTopics.ProviderStatusChange ); Services.obs.addObserver( this.torConnectObserver, TorConnectTopics.BootstrapProgress Loading Loading @@ -124,6 +130,9 @@ export class TorConnectParent extends JSWindowActorParent { Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit ); break; case "torconnect:restart-provider": TorConnect.restartProvider(); break; case "torconnect:start-again": TorConnect.startAgain(); break; Loading Loading @@ -267,3 +276,13 @@ export class TorConnectParent extends JSWindowActorParent { ); } } Services.obs.addObserver((_subject, topic) => { if (topic !== TorConnectTopics.StageChange) { return; } if (TorConnect.stageName === TorConnectStage.ProviderStopped) { // Make sure we have an open tab to show the ProviderStopped stage. TorConnectParent.open(); } }, TorConnectTopics.StageChange); browser/components/torconnect/content/aboutTorConnect.css +57 −18 Original line number Diff line number Diff line Loading @@ -235,40 +235,57 @@ form#locationDropdown select { stroke: var(--icon-color); /* Make non-interactive (non-draggable). */ pointer-events: none; } .torconnect-icon.offline-icon { &.offline-icon { content: url("chrome://browser/content/torconnect/network-broken.svg"); } .torconnect-icon.assist-icon { &.assist-icon { content: url("chrome://browser/content/torconnect/tor-connect-broken.svg"); } .torconnect-icon.location-icon { &.location-icon { content: url("chrome://browser/content/torconnect/connection-location.svg"); stroke: var(--icon-color-warning); } } .torconnect-heading { grid-area: heading; /* Do not show the focus outline. */ outline: none; font-size: var(--font-size-xxxlarge); font-size: var(--font-size-xxlarge); margin: 0; margin-block-end: var(--space-xxlarge); } .torconnect-text-container { grid-area: text-container; & > *:not(:last-child) { margin-block-end: var(--space-large); } .torconnect-text-container p { & :is(p, ul) { margin: 0; } .torconnect-text-container > *:not(:last-child) { margin-block-end: var(--space-large); & ul { padding-inline-start: var(--space-xxlarge); } & li:not(:last-child) { margin-block-end: var(--space-medium); } } .torconnect-list-intro { font-weight: var(--font-weight-semibold); } body.hide-provider-config-debugging .provider-config-debugging, body:not(.hide-provider-config-debugging) .provider-generic-debugging { display: none; } .torconnect-controls-container { Loading @@ -281,12 +298,34 @@ form#locationDropdown select { align-items: center; /* Gap between children and rows. */ gap: var(--space-small) var(--space-small); } .torconnect-controls-container > * { & > * { flex: 0 0 max-content; margin: 0; } } #restart-provider-failed { color: var(--text-color-error); align-items: center; gap: var(--space-xxsmall); &:not([hidden]) { display: flex; } & > * { flex: 0 0 max-content; } } #restart-provider-failed-icon { width: var(--icon-size); height: var(--icon-size); -moz-context-properties: fill; fill: var(--icon-color-critical); content: url("chrome://global/skin/icons/error.svg"); } /* Temporary hacks for the connectPageContainer. */ #connectPageContainer .torconnect-text-container > *:last-child { Loading browser/components/torconnect/content/aboutTorConnect.html +90 −0 Original line number Diff line number Diff line Loading @@ -15,12 +15,22 @@ href="chrome://browser/content/torconnect/aboutTorConnect.css" /> <link rel="localization" href="branding/brand.ftl" /> <link rel="localization" href="toolkit/global/tor-browser.ftl" /> <link rel="localization" href="toolkit/global/mozSupportLink.ftl" /> <script type="module" src="chrome://global/content/elements/moz-button.mjs" ></script> <script type="module" src="chrome://global/content/elements/moz-toggle.mjs" ></script> <script type="module" src="chrome://global/content/elements/moz-support-link.mjs" ></script> </head> <body class="onion-pattern-background"> <div id="progressBar" hidden="hidden"> Loading Loading @@ -50,6 +60,86 @@ <span class="breadcrumb-label"></span> </span> </div> <div class="torconnect-stage-content" data-stage-name="ProviderStopped"> <img class="torconnect-icon assist-icon" alt="" /> <h1 class="torconnect-heading" tabindex="-1" data-l10n-id="tor-connect-tor-not-working-heading" ></h1> <div class="torconnect-text-container"> <p data-l10n-id="tor-connect-tor-not-working-intro"></p> <p class="torconnect-list-intro" data-l10n-id="tor-connect-tor-not-working-cause-intro" ></p> <ul> <li class="provider-config-debugging" data-l10n-id="tor-connect-tor-not-working-cause-applications" ></li> <li class="provider-config-debugging" data-l10n-id="tor-connect-tor-not-working-cause-files" ></li> <li class="provider-config-debugging" data-l10n-id="tor-connect-tor-not-working-cause-other" ></li> <li class="provider-generic-debugging" data-l10n-id="tor-connect-tor-not-working-cause-generic" ></li> </ul> <p class="torconnect-list-intro" data-l10n-id="tor-connect-tor-not-working-resolve-intro" ></p> <ul> <li class="provider-config-debugging" data-l10n-id="tor-connect-tor-not-working-resolve-applications" ></li> <li class="provider-config-debugging" data-l10n-id="tor-connect-tor-not-working-resolve-files" ></li> <li class="provider-config-debugging" data-l10n-id="tor-connect-tor-not-working-resolve-restart-long" ></li> <li class="provider-generic-debugging" data-l10n-id="tor-connect-tor-not-working-resolve-restart-short" ></li> </ul> <p data-l10n-id="tor-connect-tor-not-working-support"> <a is="moz-support-link" data-l10n-name="support-link" support-page="tor-manual:get-in-touch__bug-or-feedback" > </a> </p> <a is="moz-support-link" support-page="tor-manual:encountering-issues__troubleshooting" ></a> </div> <div class="torconnect-controls-container"> <div id="restart-provider-failed" role="alert"> <img id="restart-provider-failed-icon" alt="" /> <span data-l10n-id="tor-connect-tor-not-working-restarting-failed" ></span> </div> <moz-button id="restart-provider-button" type="primary" data-l10n-id="tor-connect-tor-not-working-restart-button" ></moz-button> </div> </div> <div id="connectPageContainer" class="torconnect-stage-content"> <img id="tor-connect-icon" class="torconnect-icon" alt="" /> <h1 Loading browser/components/torconnect/content/aboutTorConnect.js +168 −0 Original line number Diff line number Diff line Loading @@ -134,6 +134,8 @@ class AboutTorConnect { "full-regions-option-group" ), tryBridgeButton: document.querySelector(this.selectors.buttons.tryBridge), restartProviderButton: document.getElementById("restart-provider-button"), restartProviderFailed: document.getElementById("restart-provider-failed"), }); /** Loading Loading @@ -418,6 +420,10 @@ class AboutTorConnect { console.warn("Page opened whilst loading"); isLoaded = false; break; case "ProviderStopped": this.hideBreadcrumbs(); this.updateProviderStatus(stage.providerStatus, true); break; case "Start": this.showStart(stage.tryAgain, stage.potentiallyBlocked); if (focusConnect) { Loading Loading @@ -479,6 +485,157 @@ class AboutTorConnect { moveFocus.focus(); } /** * The stored data for the `ProviderStopped` page content. `null` whilst * uninitialized. * * @type {object} */ _providerStoppedData = null; /** * Called whenever the tor provider status may have changed. Only relevant in * the `ProviderStopped` stage. * * @param {ProviderStatus} providerStatus - The latest provider status. * @param {boolean} enteringStage - Whether this is being called because we * have just entered the `ProviderStopped` stage as the initial stage of the * page, or transitioning from another stage. */ updateProviderStatus(providerStatus, enteringStage) { if (this.shownStage !== "ProviderStopped") { // Ignore. return; } if (enteringStage) { // Reset the data: // + When entering the stage. // + When opening the page in this initial stage. this._providerStoppedData = { // Set to `null` to make sure we don't early exit below. isRestarting: null, forceShowRestarting: false, canShowFailedAlert: false, // We set the maybeConfigIssue when entering the stage, but do not attempt // to update it between failed attempts. maybeConfigIssue: providerStatus.maybeConfigIssue, }; } // We show the UI as restarting if the state is not "Stopped", which // includes both "Starting" and "Running". In the latter case (which is // unexpected) we still want to show the state as loading before we enter a // different shownStage. const restarting = providerStatus.state !== "Stopped"; const data = this._providerStoppedData; if (restarting === data.isRestarting) { // No change in the recorded state. Don't change the UI or adjust any // timeouts. return; } data.isRestarting = restarting; if (restarting) { // Whilst we remain in this `ProviderStopped` stage, we will now show the // failed alert when we re-enter the "Stopped" state. data.canShowFailedAlert = true; if (!data.forceShowRestarting) { // Force the restarting UI to show for at least a certain amount of // time. Even if we fail early, we continue to show the restarting UI // for a short time to make sure the user has enough time to visually // see the restarting UI before we return to the error state. data.forceShowRestarting = true; setTimeout(() => { if ( data !== this._providerStoppedData || this.shownStage !== "ProviderStopped" ) { // We left or re-entered this stage whilst waiting. Do nothing. return; } data.forceShowRestarting = false; this.updateProviderStoppedContent(); }, 1000); } // Else, we already have a pending timeout. // E.g., consider the following timeline, where "R" represents entering // the "Starting" state, "S" represents entering the "Stopped" state, // "T0" represents the start of the forcedShowRestarting timeout, and "T1" // represents the completion: // // |--------------+-----+-----+-----+----+------------------> // S0 R0 S1 R1 S2 // T0 T1 // |--stopped UI--|--restarting UI-------|--stopped UI------- // // // Similarly with S2 delayed: // // |--------------+-----+-----+----------+----+-------------> // S0 R0 S1 R1 S2 // T0 T1 // |--stopped UI--|--restarting UI------------|--stopped UI-- // // // I.e. we restart once (R0) which starts the timeout. Then we stop (S1) and // restart (R1) again (though unlikely, this could happen if the user // opens another `about:torconnect` tab after S1 and presses the restart // button). Rather than create a new timeout, which would delay the // restart display for even longer, we maintain the current one. } this.updateProviderStoppedContent(); } /** * Whether we are currently *showing* the tor provider as restarting in the * UI. * * @type {boolean} */ restartingProvider = false; /** * Called to update the page content for the `ProviderStopped` stage. */ updateProviderStoppedContent() { const { isRestarting, forceShowRestarting, canShowFailedAlert, maybeConfigIssue, } = this._providerStoppedData; // Hide any of the debugging information related to configuration issues if // we do not suspect that this could be the cause. document.body.classList.toggle( "hide-provider-config-debugging", !maybeConfigIssue ); const showRestarting = isRestarting || forceShowRestarting; this.elements.restartProviderFailed.hidden = showRestarting || !canShowFailedAlert; this.restartingProvider = showRestarting; // The button is functionally disabled, but can still keep focus. // TODO: tor-browser#45050. Disabled attribute is waiting on bugzilla bug // 1927727. // this.elements.restartProviderButton.disabled = showRestarting; this.elements.restartProviderButton.iconSrc = showRestarting ? "chrome://global/skin/icons/loading.svg" : null; document.l10n.setAttributes( this.elements.restartProviderButton, showRestarting ? "tor-connect-tor-not-working-restarting-button" : "tor-connect-tor-not-working-restart-button" ); } updateBootstrappingStatus(data) { this.elements.progressMeter.style.setProperty( "--progress-percent", Loading Loading @@ -816,6 +973,14 @@ class AboutTorConnect { RPMSendAsyncMessage("torconnect:restart"); }); this.elements.restartProviderButton.addEventListener("click", () => { if (this.restartingProvider) { // Ignore clicks whilst the button is shown as "Restarting". return; } RPMSendAsyncMessage("torconnect:restart-provider"); }); this.elements.configureButton.textContent = TorStrings.torConnect.torConfigure; this.elements.configureButton.addEventListener("click", () => { Loading Loading @@ -896,6 +1061,9 @@ class AboutTorConnect { RPMAddMessageListener("torconnect:stage-change", ({ data }) => { this.updateStage(data); }); RPMAddMessageListener("torconnect:provider-status-change", ({ data }) => { this.updateProviderStatus(data, false); }); RPMAddMessageListener("torconnect:bootstrap-progress", ({ data }) => { this.updateBootstrappingStatus(data); }); Loading toolkit/modules/RemotePageAccessManager.sys.mjs +3 −0 Original line number Diff line number Diff line Loading @@ -288,6 +288,7 @@ export let RemotePageAccessManager = { "about:torconnect": { RPMAddMessageListener: [ "torconnect:stage-change", "torconnect:provider-status-change", "torconnect:bootstrap-progress", "torconnect:quickstart-change", "torconnect:region-names-change", Loading @@ -299,10 +300,12 @@ export let RemotePageAccessManager = { "torconnect:set-quickstart", "torconnect:view-tor-logs", "torconnect:restart", "torconnect:restart-provider", "torconnect:start-again", "torconnect:choose-region", ], RPMSendQuery: ["torconnect:get-init-args", "torconnect:get-regions"], RPMGetFormatURLPref: ["app.support.baseURL"], }, "about:welcome": { RPMSendAsyncMessage: ["ActivityStream:ContentToMain"], Loading Loading
browser/components/torconnect/TorConnectParent.sys.mjs +22 −3 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ import { TorStrings } from "moz-src:///toolkit/modules/TorStrings.sys.mjs"; import { TorConnect, TorConnectStage, TorConnectTopics, } from "moz-src:///toolkit/modules/TorConnect.sys.mjs"; Loading @@ -26,9 +27,7 @@ and a particular about:torconnect page * It adapts and relays the messages from and to the TorConnect module. */ export class TorConnectParent extends JSWindowActorParent { constructor(...args) { super(...args); actorCreated() { const self = this; // JSWindowActiveParent derived objects cannot observe directly, so create a Loading @@ -44,6 +43,9 @@ export class TorConnectParent extends JSWindowActorParent { case TorConnectTopics.StageChange: self.sendAsyncMessage("torconnect:stage-change", obj); break; case TorConnectTopics.ProviderStatusChange: self.sendAsyncMessage("torconnect:provider-status-change", obj); break; case TorConnectTopics.BootstrapProgress: self.sendAsyncMessage("torconnect:bootstrap-progress", obj); break; Loading @@ -64,6 +66,10 @@ export class TorConnectParent extends JSWindowActorParent { this.torConnectObserver, TorConnectTopics.StageChange ); Services.obs.addObserver( this.torConnectObserver, TorConnectTopics.ProviderStatusChange ); Services.obs.addObserver( this.torConnectObserver, TorConnectTopics.BootstrapProgress Loading Loading @@ -124,6 +130,9 @@ export class TorConnectParent extends JSWindowActorParent { Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit ); break; case "torconnect:restart-provider": TorConnect.restartProvider(); break; case "torconnect:start-again": TorConnect.startAgain(); break; Loading Loading @@ -267,3 +276,13 @@ export class TorConnectParent extends JSWindowActorParent { ); } } Services.obs.addObserver((_subject, topic) => { if (topic !== TorConnectTopics.StageChange) { return; } if (TorConnect.stageName === TorConnectStage.ProviderStopped) { // Make sure we have an open tab to show the ProviderStopped stage. TorConnectParent.open(); } }, TorConnectTopics.StageChange);
browser/components/torconnect/content/aboutTorConnect.css +57 −18 Original line number Diff line number Diff line Loading @@ -235,40 +235,57 @@ form#locationDropdown select { stroke: var(--icon-color); /* Make non-interactive (non-draggable). */ pointer-events: none; } .torconnect-icon.offline-icon { &.offline-icon { content: url("chrome://browser/content/torconnect/network-broken.svg"); } .torconnect-icon.assist-icon { &.assist-icon { content: url("chrome://browser/content/torconnect/tor-connect-broken.svg"); } .torconnect-icon.location-icon { &.location-icon { content: url("chrome://browser/content/torconnect/connection-location.svg"); stroke: var(--icon-color-warning); } } .torconnect-heading { grid-area: heading; /* Do not show the focus outline. */ outline: none; font-size: var(--font-size-xxxlarge); font-size: var(--font-size-xxlarge); margin: 0; margin-block-end: var(--space-xxlarge); } .torconnect-text-container { grid-area: text-container; & > *:not(:last-child) { margin-block-end: var(--space-large); } .torconnect-text-container p { & :is(p, ul) { margin: 0; } .torconnect-text-container > *:not(:last-child) { margin-block-end: var(--space-large); & ul { padding-inline-start: var(--space-xxlarge); } & li:not(:last-child) { margin-block-end: var(--space-medium); } } .torconnect-list-intro { font-weight: var(--font-weight-semibold); } body.hide-provider-config-debugging .provider-config-debugging, body:not(.hide-provider-config-debugging) .provider-generic-debugging { display: none; } .torconnect-controls-container { Loading @@ -281,12 +298,34 @@ form#locationDropdown select { align-items: center; /* Gap between children and rows. */ gap: var(--space-small) var(--space-small); } .torconnect-controls-container > * { & > * { flex: 0 0 max-content; margin: 0; } } #restart-provider-failed { color: var(--text-color-error); align-items: center; gap: var(--space-xxsmall); &:not([hidden]) { display: flex; } & > * { flex: 0 0 max-content; } } #restart-provider-failed-icon { width: var(--icon-size); height: var(--icon-size); -moz-context-properties: fill; fill: var(--icon-color-critical); content: url("chrome://global/skin/icons/error.svg"); } /* Temporary hacks for the connectPageContainer. */ #connectPageContainer .torconnect-text-container > *:last-child { Loading
browser/components/torconnect/content/aboutTorConnect.html +90 −0 Original line number Diff line number Diff line Loading @@ -15,12 +15,22 @@ href="chrome://browser/content/torconnect/aboutTorConnect.css" /> <link rel="localization" href="branding/brand.ftl" /> <link rel="localization" href="toolkit/global/tor-browser.ftl" /> <link rel="localization" href="toolkit/global/mozSupportLink.ftl" /> <script type="module" src="chrome://global/content/elements/moz-button.mjs" ></script> <script type="module" src="chrome://global/content/elements/moz-toggle.mjs" ></script> <script type="module" src="chrome://global/content/elements/moz-support-link.mjs" ></script> </head> <body class="onion-pattern-background"> <div id="progressBar" hidden="hidden"> Loading Loading @@ -50,6 +60,86 @@ <span class="breadcrumb-label"></span> </span> </div> <div class="torconnect-stage-content" data-stage-name="ProviderStopped"> <img class="torconnect-icon assist-icon" alt="" /> <h1 class="torconnect-heading" tabindex="-1" data-l10n-id="tor-connect-tor-not-working-heading" ></h1> <div class="torconnect-text-container"> <p data-l10n-id="tor-connect-tor-not-working-intro"></p> <p class="torconnect-list-intro" data-l10n-id="tor-connect-tor-not-working-cause-intro" ></p> <ul> <li class="provider-config-debugging" data-l10n-id="tor-connect-tor-not-working-cause-applications" ></li> <li class="provider-config-debugging" data-l10n-id="tor-connect-tor-not-working-cause-files" ></li> <li class="provider-config-debugging" data-l10n-id="tor-connect-tor-not-working-cause-other" ></li> <li class="provider-generic-debugging" data-l10n-id="tor-connect-tor-not-working-cause-generic" ></li> </ul> <p class="torconnect-list-intro" data-l10n-id="tor-connect-tor-not-working-resolve-intro" ></p> <ul> <li class="provider-config-debugging" data-l10n-id="tor-connect-tor-not-working-resolve-applications" ></li> <li class="provider-config-debugging" data-l10n-id="tor-connect-tor-not-working-resolve-files" ></li> <li class="provider-config-debugging" data-l10n-id="tor-connect-tor-not-working-resolve-restart-long" ></li> <li class="provider-generic-debugging" data-l10n-id="tor-connect-tor-not-working-resolve-restart-short" ></li> </ul> <p data-l10n-id="tor-connect-tor-not-working-support"> <a is="moz-support-link" data-l10n-name="support-link" support-page="tor-manual:get-in-touch__bug-or-feedback" > </a> </p> <a is="moz-support-link" support-page="tor-manual:encountering-issues__troubleshooting" ></a> </div> <div class="torconnect-controls-container"> <div id="restart-provider-failed" role="alert"> <img id="restart-provider-failed-icon" alt="" /> <span data-l10n-id="tor-connect-tor-not-working-restarting-failed" ></span> </div> <moz-button id="restart-provider-button" type="primary" data-l10n-id="tor-connect-tor-not-working-restart-button" ></moz-button> </div> </div> <div id="connectPageContainer" class="torconnect-stage-content"> <img id="tor-connect-icon" class="torconnect-icon" alt="" /> <h1 Loading
browser/components/torconnect/content/aboutTorConnect.js +168 −0 Original line number Diff line number Diff line Loading @@ -134,6 +134,8 @@ class AboutTorConnect { "full-regions-option-group" ), tryBridgeButton: document.querySelector(this.selectors.buttons.tryBridge), restartProviderButton: document.getElementById("restart-provider-button"), restartProviderFailed: document.getElementById("restart-provider-failed"), }); /** Loading Loading @@ -418,6 +420,10 @@ class AboutTorConnect { console.warn("Page opened whilst loading"); isLoaded = false; break; case "ProviderStopped": this.hideBreadcrumbs(); this.updateProviderStatus(stage.providerStatus, true); break; case "Start": this.showStart(stage.tryAgain, stage.potentiallyBlocked); if (focusConnect) { Loading Loading @@ -479,6 +485,157 @@ class AboutTorConnect { moveFocus.focus(); } /** * The stored data for the `ProviderStopped` page content. `null` whilst * uninitialized. * * @type {object} */ _providerStoppedData = null; /** * Called whenever the tor provider status may have changed. Only relevant in * the `ProviderStopped` stage. * * @param {ProviderStatus} providerStatus - The latest provider status. * @param {boolean} enteringStage - Whether this is being called because we * have just entered the `ProviderStopped` stage as the initial stage of the * page, or transitioning from another stage. */ updateProviderStatus(providerStatus, enteringStage) { if (this.shownStage !== "ProviderStopped") { // Ignore. return; } if (enteringStage) { // Reset the data: // + When entering the stage. // + When opening the page in this initial stage. this._providerStoppedData = { // Set to `null` to make sure we don't early exit below. isRestarting: null, forceShowRestarting: false, canShowFailedAlert: false, // We set the maybeConfigIssue when entering the stage, but do not attempt // to update it between failed attempts. maybeConfigIssue: providerStatus.maybeConfigIssue, }; } // We show the UI as restarting if the state is not "Stopped", which // includes both "Starting" and "Running". In the latter case (which is // unexpected) we still want to show the state as loading before we enter a // different shownStage. const restarting = providerStatus.state !== "Stopped"; const data = this._providerStoppedData; if (restarting === data.isRestarting) { // No change in the recorded state. Don't change the UI or adjust any // timeouts. return; } data.isRestarting = restarting; if (restarting) { // Whilst we remain in this `ProviderStopped` stage, we will now show the // failed alert when we re-enter the "Stopped" state. data.canShowFailedAlert = true; if (!data.forceShowRestarting) { // Force the restarting UI to show for at least a certain amount of // time. Even if we fail early, we continue to show the restarting UI // for a short time to make sure the user has enough time to visually // see the restarting UI before we return to the error state. data.forceShowRestarting = true; setTimeout(() => { if ( data !== this._providerStoppedData || this.shownStage !== "ProviderStopped" ) { // We left or re-entered this stage whilst waiting. Do nothing. return; } data.forceShowRestarting = false; this.updateProviderStoppedContent(); }, 1000); } // Else, we already have a pending timeout. // E.g., consider the following timeline, where "R" represents entering // the "Starting" state, "S" represents entering the "Stopped" state, // "T0" represents the start of the forcedShowRestarting timeout, and "T1" // represents the completion: // // |--------------+-----+-----+-----+----+------------------> // S0 R0 S1 R1 S2 // T0 T1 // |--stopped UI--|--restarting UI-------|--stopped UI------- // // // Similarly with S2 delayed: // // |--------------+-----+-----+----------+----+-------------> // S0 R0 S1 R1 S2 // T0 T1 // |--stopped UI--|--restarting UI------------|--stopped UI-- // // // I.e. we restart once (R0) which starts the timeout. Then we stop (S1) and // restart (R1) again (though unlikely, this could happen if the user // opens another `about:torconnect` tab after S1 and presses the restart // button). Rather than create a new timeout, which would delay the // restart display for even longer, we maintain the current one. } this.updateProviderStoppedContent(); } /** * Whether we are currently *showing* the tor provider as restarting in the * UI. * * @type {boolean} */ restartingProvider = false; /** * Called to update the page content for the `ProviderStopped` stage. */ updateProviderStoppedContent() { const { isRestarting, forceShowRestarting, canShowFailedAlert, maybeConfigIssue, } = this._providerStoppedData; // Hide any of the debugging information related to configuration issues if // we do not suspect that this could be the cause. document.body.classList.toggle( "hide-provider-config-debugging", !maybeConfigIssue ); const showRestarting = isRestarting || forceShowRestarting; this.elements.restartProviderFailed.hidden = showRestarting || !canShowFailedAlert; this.restartingProvider = showRestarting; // The button is functionally disabled, but can still keep focus. // TODO: tor-browser#45050. Disabled attribute is waiting on bugzilla bug // 1927727. // this.elements.restartProviderButton.disabled = showRestarting; this.elements.restartProviderButton.iconSrc = showRestarting ? "chrome://global/skin/icons/loading.svg" : null; document.l10n.setAttributes( this.elements.restartProviderButton, showRestarting ? "tor-connect-tor-not-working-restarting-button" : "tor-connect-tor-not-working-restart-button" ); } updateBootstrappingStatus(data) { this.elements.progressMeter.style.setProperty( "--progress-percent", Loading Loading @@ -816,6 +973,14 @@ class AboutTorConnect { RPMSendAsyncMessage("torconnect:restart"); }); this.elements.restartProviderButton.addEventListener("click", () => { if (this.restartingProvider) { // Ignore clicks whilst the button is shown as "Restarting". return; } RPMSendAsyncMessage("torconnect:restart-provider"); }); this.elements.configureButton.textContent = TorStrings.torConnect.torConfigure; this.elements.configureButton.addEventListener("click", () => { Loading Loading @@ -896,6 +1061,9 @@ class AboutTorConnect { RPMAddMessageListener("torconnect:stage-change", ({ data }) => { this.updateStage(data); }); RPMAddMessageListener("torconnect:provider-status-change", ({ data }) => { this.updateProviderStatus(data, false); }); RPMAddMessageListener("torconnect:bootstrap-progress", ({ data }) => { this.updateBootstrappingStatus(data); }); Loading
toolkit/modules/RemotePageAccessManager.sys.mjs +3 −0 Original line number Diff line number Diff line Loading @@ -288,6 +288,7 @@ export let RemotePageAccessManager = { "about:torconnect": { RPMAddMessageListener: [ "torconnect:stage-change", "torconnect:provider-status-change", "torconnect:bootstrap-progress", "torconnect:quickstart-change", "torconnect:region-names-change", Loading @@ -299,10 +300,12 @@ export let RemotePageAccessManager = { "torconnect:set-quickstart", "torconnect:view-tor-logs", "torconnect:restart", "torconnect:restart-provider", "torconnect:start-again", "torconnect:choose-region", ], RPMSendQuery: ["torconnect:get-init-args", "torconnect:get-regions"], RPMGetFormatURLPref: ["app.support.baseURL"], }, "about:welcome": { RPMSendAsyncMessage: ["ActivityStream:ContentToMain"], Loading