Loading browser/components/torconnect/TorConnectChild.sys.mjs +75 −1 Original line number Diff line number Diff line Loading @@ -2,4 +2,78 @@ import { RemotePageChild } from "resource://gre/actors/RemotePageChild.sys.mjs"; export class TorConnectChild extends RemotePageChild {} export class TorConnectChild extends RemotePageChild { /** * Whether we have redirected the page (after bootstrapping) or not. * * @type {boolean} */ #redirected = false; /** * If bootstrapping is complete, or TorConnect is disabled, we redirect the * page. */ async #maybeRedirect() { if (await this.sendQuery("torconnect:should-show")) { // Enabled and not yet bootstrapped. return; } if (this.#redirected) { return; } this.#redirected = true; const redirect = new URLSearchParams( new URL(this.contentWindow.document.location.href).search ).get("redirect"); // Fallback in error cases: let replaceURI = "about:tor"; try { const url = new URL( redirect ? decodeURIComponent(redirect) : // NOTE: We expect no redirect when address is entered manually, or // about:torconnect is opened from preferences or urlbar. // Go to the home page. await this.sendQuery("torconnect:home-page") ); // Do not allow javascript URI. See tor-browser#41766 if ( ["about:", "file:", "https:", "http:"].includes(url.protocol) || // Allow blank page. See tor-browser#42184. // Blank page's are given as a chrome URL rather than "about:blank". url.href === "chrome://browser/content/blanktab.html" ) { replaceURI = url.href; } else { console.error(`Scheme is not allowed "${redirect}"`); } } catch { console.error(`Invalid redirect URL "${redirect}"`); } // Replace the destination to prevent "about:torconnect" entering the // history. // NOTE: This is done here, in the window actor, rather than in content // because we have the privilege to redirect to a "chrome:" uri here (for // when the HomePage is set to be blank). this.contentWindow.location.replace(replaceURI); } actorCreated() { super.actorCreated(); // about:torconnect could need to be immediately redirected. E.g. if it is // reached after bootstrapping. this.#maybeRedirect(); } receiveMessage(message) { super.receiveMessage(message); if (message.name === "torconnect:state-change") { this.#maybeRedirect(); } } } browser/components/torconnect/TorConnectParent.sys.mjs +13 −0 Original line number Diff line number Diff line // Copyright (c) 2021, The Tor Project, Inc. import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; const { TorStrings } = ChromeUtils.import("resource:///modules/TorStrings.jsm"); import { InternetStatus, Loading @@ -15,6 +17,12 @@ import { const BroadcastTopic = "about-torconnect:broadcast"; const lazy = {}; XPCOMUtils.defineLazyModuleGetters(lazy, { HomePage: "resource:///modules/HomePage.jsm", }); /* This object is basically a marshalling interface between the TorConnect module and a particular about:torconnect page Loading Loading @@ -167,6 +175,11 @@ export class TorConnectParent extends JSWindowActorParent { async receiveMessage(message) { switch (message.name) { case "torconnect:should-show": return Promise.resolve(TorConnect.shouldShowTorConnect); case "torconnect:home-page": // If there are multiple home pages, just load the first one. return Promise.resolve(TorConnect.fixupURIs(lazy.HomePage.get())[0]); case "torconnect:set-quickstart": TorSettings.quickstart.enabled = message.data; TorSettings.saveToPrefs().applySettings(); Loading browser/components/torconnect/content/aboutTorConnect.js +0 −26 Original line number Diff line number Diff line Loading @@ -136,10 +136,6 @@ class AboutTorConnect { tryBridgeButton: document.querySelector(this.selectors.buttons.tryBridge), }); // a redirect url can be passed as a query parameter for the page to // forward us to once bootstrap completes (otherwise the window will just close) redirect = null; uiState = { currentState: UIStates.ConnectToTor, allowAutomaticLocation: true, Loading Loading @@ -425,11 +421,6 @@ class AboutTorConnect { this.setLongText(TorStrings.settings.torPreferencesDescription); this.setProgress("", showProgressbar, 100); this.hideButtons(); // redirects page to the requested redirect url, removes about:torconnect // from the page stack, so users cannot accidentally go 'back' to the // now unresponsive page window.location.replace(this.redirect); } update_Disabled(state) { Loading Loading @@ -822,23 +813,6 @@ class AboutTorConnect { } async init() { // if the user gets here manually or via the button in the urlbar // then we will redirect to about:tor this.redirect = "about:tor"; // see if a user has a final destination after bootstrapping let params = new URLSearchParams(new URL(document.location.href).search); if (params.has("redirect")) { try { const redirect = new URL(decodeURIComponent(params.get("redirect"))); if (/^(?:https?|about):$/.test(redirect.protocol)) { this.redirect = redirect.href; } } catch (e) { console.error(e, `Invalid redirect URL "${params.get("redirect")}"!`); } } let args = await RPMSendQuery("torconnect:get-init-args"); // various constants Loading Loading
browser/components/torconnect/TorConnectChild.sys.mjs +75 −1 Original line number Diff line number Diff line Loading @@ -2,4 +2,78 @@ import { RemotePageChild } from "resource://gre/actors/RemotePageChild.sys.mjs"; export class TorConnectChild extends RemotePageChild {} export class TorConnectChild extends RemotePageChild { /** * Whether we have redirected the page (after bootstrapping) or not. * * @type {boolean} */ #redirected = false; /** * If bootstrapping is complete, or TorConnect is disabled, we redirect the * page. */ async #maybeRedirect() { if (await this.sendQuery("torconnect:should-show")) { // Enabled and not yet bootstrapped. return; } if (this.#redirected) { return; } this.#redirected = true; const redirect = new URLSearchParams( new URL(this.contentWindow.document.location.href).search ).get("redirect"); // Fallback in error cases: let replaceURI = "about:tor"; try { const url = new URL( redirect ? decodeURIComponent(redirect) : // NOTE: We expect no redirect when address is entered manually, or // about:torconnect is opened from preferences or urlbar. // Go to the home page. await this.sendQuery("torconnect:home-page") ); // Do not allow javascript URI. See tor-browser#41766 if ( ["about:", "file:", "https:", "http:"].includes(url.protocol) || // Allow blank page. See tor-browser#42184. // Blank page's are given as a chrome URL rather than "about:blank". url.href === "chrome://browser/content/blanktab.html" ) { replaceURI = url.href; } else { console.error(`Scheme is not allowed "${redirect}"`); } } catch { console.error(`Invalid redirect URL "${redirect}"`); } // Replace the destination to prevent "about:torconnect" entering the // history. // NOTE: This is done here, in the window actor, rather than in content // because we have the privilege to redirect to a "chrome:" uri here (for // when the HomePage is set to be blank). this.contentWindow.location.replace(replaceURI); } actorCreated() { super.actorCreated(); // about:torconnect could need to be immediately redirected. E.g. if it is // reached after bootstrapping. this.#maybeRedirect(); } receiveMessage(message) { super.receiveMessage(message); if (message.name === "torconnect:state-change") { this.#maybeRedirect(); } } }
browser/components/torconnect/TorConnectParent.sys.mjs +13 −0 Original line number Diff line number Diff line // Copyright (c) 2021, The Tor Project, Inc. import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; const { TorStrings } = ChromeUtils.import("resource:///modules/TorStrings.jsm"); import { InternetStatus, Loading @@ -15,6 +17,12 @@ import { const BroadcastTopic = "about-torconnect:broadcast"; const lazy = {}; XPCOMUtils.defineLazyModuleGetters(lazy, { HomePage: "resource:///modules/HomePage.jsm", }); /* This object is basically a marshalling interface between the TorConnect module and a particular about:torconnect page Loading Loading @@ -167,6 +175,11 @@ export class TorConnectParent extends JSWindowActorParent { async receiveMessage(message) { switch (message.name) { case "torconnect:should-show": return Promise.resolve(TorConnect.shouldShowTorConnect); case "torconnect:home-page": // If there are multiple home pages, just load the first one. return Promise.resolve(TorConnect.fixupURIs(lazy.HomePage.get())[0]); case "torconnect:set-quickstart": TorSettings.quickstart.enabled = message.data; TorSettings.saveToPrefs().applySettings(); Loading
browser/components/torconnect/content/aboutTorConnect.js +0 −26 Original line number Diff line number Diff line Loading @@ -136,10 +136,6 @@ class AboutTorConnect { tryBridgeButton: document.querySelector(this.selectors.buttons.tryBridge), }); // a redirect url can be passed as a query parameter for the page to // forward us to once bootstrap completes (otherwise the window will just close) redirect = null; uiState = { currentState: UIStates.ConnectToTor, allowAutomaticLocation: true, Loading Loading @@ -425,11 +421,6 @@ class AboutTorConnect { this.setLongText(TorStrings.settings.torPreferencesDescription); this.setProgress("", showProgressbar, 100); this.hideButtons(); // redirects page to the requested redirect url, removes about:torconnect // from the page stack, so users cannot accidentally go 'back' to the // now unresponsive page window.location.replace(this.redirect); } update_Disabled(state) { Loading Loading @@ -822,23 +813,6 @@ class AboutTorConnect { } async init() { // if the user gets here manually or via the button in the urlbar // then we will redirect to about:tor this.redirect = "about:tor"; // see if a user has a final destination after bootstrapping let params = new URLSearchParams(new URL(document.location.href).search); if (params.has("redirect")) { try { const redirect = new URL(decodeURIComponent(params.get("redirect"))); if (/^(?:https?|about):$/.test(redirect.protocol)) { this.redirect = redirect.href; } } catch (e) { console.error(e, `Invalid redirect URL "${params.get("redirect")}"!`); } } let args = await RPMSendQuery("torconnect:get-init-args"); // various constants Loading