ma1 pushed to branch tor-browser-115.4.0esr-13.5-1 at The Tor Project / Applications / Tor Browser

Commits:

4 changed files:

Changes:

  • browser/components/torconnect/TorConnectChild.sys.mjs
    ... ... @@ -2,4 +2,78 @@
    2 2
     
    
    3 3
     import { RemotePageChild } from "resource://gre/actors/RemotePageChild.sys.mjs";
    
    4 4
     
    
    5
    -export class TorConnectChild extends RemotePageChild {}
    5
    +export class TorConnectChild extends RemotePageChild {
    
    6
    +  /**
    
    7
    +   * Whether we have redirected the page (after bootstrapping) or not.
    
    8
    +   *
    
    9
    +   * @type {boolean}
    
    10
    +   */
    
    11
    +  #redirected = false;
    
    12
    +
    
    13
    +  /**
    
    14
    +   * If bootstrapping is complete, or TorConnect is disabled, we redirect the
    
    15
    +   * page.
    
    16
    +   */
    
    17
    +  async #maybeRedirect() {
    
    18
    +    if (await this.sendQuery("torconnect:should-show")) {
    
    19
    +      // Enabled and not yet bootstrapped.
    
    20
    +      return;
    
    21
    +    }
    
    22
    +    if (this.#redirected) {
    
    23
    +      return;
    
    24
    +    }
    
    25
    +    this.#redirected = true;
    
    26
    +
    
    27
    +    const redirect = new URLSearchParams(
    
    28
    +      new URL(this.contentWindow.document.location.href).search
    
    29
    +    ).get("redirect");
    
    30
    +
    
    31
    +    // Fallback in error cases:
    
    32
    +    let replaceURI = "about:tor";
    
    33
    +    try {
    
    34
    +      const url = new URL(
    
    35
    +        redirect
    
    36
    +          ? decodeURIComponent(redirect)
    
    37
    +          : // NOTE: We expect no redirect when address is entered manually, or
    
    38
    +            // about:torconnect is opened from preferences or urlbar.
    
    39
    +            // Go to the home page.
    
    40
    +            await this.sendQuery("torconnect:home-page")
    
    41
    +      );
    
    42
    +      // Do not allow javascript URI. See tor-browser#41766
    
    43
    +      if (
    
    44
    +        ["about:", "file:", "https:", "http:"].includes(url.protocol) ||
    
    45
    +        // Allow blank page. See tor-browser#42184.
    
    46
    +        // Blank page's are given as a chrome URL rather than "about:blank".
    
    47
    +        url.href === "chrome://browser/content/blanktab.html"
    
    48
    +      ) {
    
    49
    +        replaceURI = url.href;
    
    50
    +      } else {
    
    51
    +        console.error(`Scheme is not allowed "${redirect}"`);
    
    52
    +      }
    
    53
    +    } catch {
    
    54
    +      console.error(`Invalid redirect URL "${redirect}"`);
    
    55
    +    }
    
    56
    +
    
    57
    +    // Replace the destination to prevent "about:torconnect" entering the
    
    58
    +    // history.
    
    59
    +    // NOTE: This is done here, in the window actor, rather than in content
    
    60
    +    // because we have the privilege to redirect to a "chrome:" uri here (for
    
    61
    +    // when the HomePage is set to be blank).
    
    62
    +    this.contentWindow.location.replace(replaceURI);
    
    63
    +  }
    
    64
    +
    
    65
    +  actorCreated() {
    
    66
    +    super.actorCreated();
    
    67
    +    // about:torconnect could need to be immediately redirected. E.g. if it is
    
    68
    +    // reached after bootstrapping.
    
    69
    +    this.#maybeRedirect();
    
    70
    +  }
    
    71
    +
    
    72
    +  receiveMessage(message) {
    
    73
    +    super.receiveMessage(message);
    
    74
    +
    
    75
    +    if (message.name === "torconnect:state-change") {
    
    76
    +      this.#maybeRedirect();
    
    77
    +    }
    
    78
    +  }
    
    79
    +}

  • browser/components/torconnect/TorConnectParent.sys.mjs
    1 1
     // Copyright (c) 2021, The Tor Project, Inc.
    
    2 2
     
    
    3
    +import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
    
    4
    +
    
    3 5
     const { TorStrings } = ChromeUtils.import("resource:///modules/TorStrings.jsm");
    
    4 6
     import {
    
    5 7
       InternetStatus,
    
    ... ... @@ -15,6 +17,12 @@ import {
    15 17
     
    
    16 18
     const BroadcastTopic = "about-torconnect:broadcast";
    
    17 19
     
    
    20
    +const lazy = {};
    
    21
    +
    
    22
    +XPCOMUtils.defineLazyModuleGetters(lazy, {
    
    23
    +  HomePage: "resource:///modules/HomePage.jsm",
    
    24
    +});
    
    25
    +
    
    18 26
     /*
    
    19 27
     This object is basically a marshalling interface between the TorConnect module
    
    20 28
     and a particular about:torconnect page
    
    ... ... @@ -167,6 +175,11 @@ export class TorConnectParent extends JSWindowActorParent {
    167 175
     
    
    168 176
       async receiveMessage(message) {
    
    169 177
         switch (message.name) {
    
    178
    +      case "torconnect:should-show":
    
    179
    +        return Promise.resolve(TorConnect.shouldShowTorConnect);
    
    180
    +      case "torconnect:home-page":
    
    181
    +        // If there are multiple home pages, just load the first one.
    
    182
    +        return Promise.resolve(TorConnect.fixupURIs(lazy.HomePage.get())[0]);
    
    170 183
           case "torconnect:set-quickstart":
    
    171 184
             TorSettings.quickstart.enabled = message.data;
    
    172 185
             TorSettings.saveToPrefs().applySettings();
    

  • browser/components/torconnect/content/aboutTorConnect.js
    ... ... @@ -136,10 +136,6 @@ class AboutTorConnect {
    136 136
         tryBridgeButton: document.querySelector(this.selectors.buttons.tryBridge),
    
    137 137
       });
    
    138 138
     
    
    139
    -  // a redirect url can be passed as a query parameter for the page to
    
    140
    -  // forward us to once bootstrap completes (otherwise the window will just close)
    
    141
    -  redirect = null;
    
    142
    -
    
    143 139
       uiState = {
    
    144 140
         currentState: UIStates.ConnectToTor,
    
    145 141
         allowAutomaticLocation: true,
    
    ... ... @@ -425,11 +421,6 @@ class AboutTorConnect {
    425 421
         this.setLongText(TorStrings.settings.torPreferencesDescription);
    
    426 422
         this.setProgress("", showProgressbar, 100);
    
    427 423
         this.hideButtons();
    
    428
    -
    
    429
    -    // redirects page to the requested redirect url, removes about:torconnect
    
    430
    -    // from the page stack, so users cannot accidentally go 'back' to the
    
    431
    -    // now unresponsive page
    
    432
    -    window.location.replace(this.redirect);
    
    433 424
       }
    
    434 425
     
    
    435 426
       update_Disabled(state) {
    
    ... ... @@ -822,23 +813,6 @@ class AboutTorConnect {
    822 813
       }
    
    823 814
     
    
    824 815
       async init() {
    
    825
    -    // if the user gets here manually or via the button in the urlbar
    
    826
    -    // then we will redirect to about:tor
    
    827
    -    this.redirect = "about:tor";
    
    828
    -
    
    829
    -    // see if a user has a final destination after bootstrapping
    
    830
    -    let params = new URLSearchParams(new URL(document.location.href).search);
    
    831
    -    if (params.has("redirect")) {
    
    832
    -      try {
    
    833
    -        const redirect = new URL(decodeURIComponent(params.get("redirect")));
    
    834
    -        if (/^(?:https?|about):$/.test(redirect.protocol)) {
    
    835
    -          this.redirect = redirect.href;
    
    836
    -        }
    
    837
    -      } catch (e) {
    
    838
    -        console.error(e, `Invalid redirect URL "${params.get("redirect")}"!`);
    
    839
    -      }
    
    840
    -    }
    
    841
    -
    
    842 816
         let args = await RPMSendQuery("torconnect:get-init-args");
    
    843 817
     
    
    844 818
         // various constants
    

  • browser/modules/TorConnect.sys.mjs
    ... ... @@ -1156,67 +1156,54 @@ export const TorConnect = (() => {
    1156 1156
           return `about:torconnect?redirect=${encodeURIComponent(url)}`;
    
    1157 1157
         },
    
    1158 1158
     
    
    1159
    +    /**
    
    1160
    +     * Convert the given object into a list of valid URIs.
    
    1161
    +     *
    
    1162
    +     * The object is either from the user's homepage preference (which may
    
    1163
    +     * contain multiple domains separated by "|") or uris passed to the browser
    
    1164
    +     * via command-line.
    
    1165
    +     *
    
    1166
    +     * @param {string|string[]} uriVariant - The string to extract uris from.
    
    1167
    +     *
    
    1168
    +     * @return {string[]} - The array of uris found.
    
    1169
    +     */
    
    1170
    +    fixupURIs(uriVariant) {
    
    1171
    +      let uriArray;
    
    1172
    +      if (typeof uriVariant === "string") {
    
    1173
    +        uriArray = uriVariant.split("|");
    
    1174
    +      } else if (
    
    1175
    +        Array.isArray(uriVariant) &&
    
    1176
    +        uriVariant.every(entry => typeof entry === "string")
    
    1177
    +      ) {
    
    1178
    +        uriArray = uriVariant;
    
    1179
    +      } else {
    
    1180
    +        // about:tor as safe fallback
    
    1181
    +        console.error(
    
    1182
    +          `TorConnect: received unknown variant '${JSON.stringify(uriVariant)}'`
    
    1183
    +        );
    
    1184
    +        uriArray = ["about:tor"];
    
    1185
    +      }
    
    1186
    +
    
    1187
    +      // Attempt to convert user-supplied string to a uri, fallback to
    
    1188
    +      // about:tor if cannot convert to valid uri object
    
    1189
    +      return uriArray.map(
    
    1190
    +        uriString =>
    
    1191
    +          Services.uriFixup.getFixupURIInfo(
    
    1192
    +            uriString,
    
    1193
    +            Ci.nsIURIFixup.FIXUP_FLAG_NONE
    
    1194
    +          ).preferredURI?.spec ?? "about:tor"
    
    1195
    +      );
    
    1196
    +    },
    
    1197
    +
    
    1159 1198
         // called from browser.js on browser startup, passed in either the user's homepage(s)
    
    1160 1199
         // or uris passed via command-line; we want to replace them with about:torconnect uris
    
    1161 1200
         // which redirect after bootstrapping
    
    1162 1201
         getURIsToLoad(uriVariant) {
    
    1163
    -      // convert the object we get from browser.js
    
    1164
    -      let uriStrings = (v => {
    
    1165
    -        // an interop array
    
    1166
    -        if (v instanceof Ci.nsIArray) {
    
    1167
    -          // Transform the nsIArray of nsISupportsString's into a JS Array of
    
    1168
    -          // JS strings.
    
    1169
    -          return Array.from(
    
    1170
    -            v.enumerate(Ci.nsISupportsString),
    
    1171
    -            supportStr => supportStr.data
    
    1172
    -          );
    
    1173
    -          // an interop string
    
    1174
    -        } else if (v instanceof Ci.nsISupportsString) {
    
    1175
    -          return [v.data];
    
    1176
    -          // a js string
    
    1177
    -        } else if (typeof v === "string") {
    
    1178
    -          return v.split("|");
    
    1179
    -          // a js array of js strings
    
    1180
    -        } else if (
    
    1181
    -          Array.isArray(v) &&
    
    1182
    -          v.reduce((allStrings, entry) => {
    
    1183
    -            return allStrings && typeof entry === "string";
    
    1184
    -          }, true)
    
    1185
    -        ) {
    
    1186
    -          return v;
    
    1187
    -        }
    
    1188
    -        // about:tor as safe fallback
    
    1189
    -        console.log(
    
    1190
    -          `TorConnect: getURIsToLoad() received unknown variant '${JSON.stringify(
    
    1191
    -            v
    
    1192
    -          )}'`
    
    1193
    -        );
    
    1194
    -        return ["about:tor"];
    
    1195
    -      })(uriVariant);
    
    1196
    -
    
    1197
    -      // will attempt to convert user-supplied string to a uri, fallback to about:tor if cannot convert
    
    1198
    -      // to valid uri object
    
    1199
    -      let uriStringToUri = uriString => {
    
    1200
    -        const fixupFlags = Ci.nsIURIFixup.FIXUP_FLAG_NONE;
    
    1201
    -        let uri = Services.uriFixup.getFixupURIInfo(
    
    1202
    -          uriString,
    
    1203
    -          fixupFlags
    
    1204
    -        ).preferredURI;
    
    1205
    -        return uri ? uri : Services.io.newURI("about:tor");
    
    1206
    -      };
    
    1207
    -      let uris = uriStrings.map(uriStringToUri);
    
    1208
    -
    
    1209
    -      // assume we have a valid uri and generate an about:torconnect redirect uri
    
    1210
    -      let redirectUrls = uris.map(uri => this.getRedirectURL(uri.spec));
    
    1211
    -
    
    1202
    +      const uris = this.fixupURIs(uriVariant);
    
    1212 1203
           console.log(
    
    1213
    -        `TorConnect: Will load after bootstrap => [${uris
    
    1214
    -          .map(uri => {
    
    1215
    -            return uri.spec;
    
    1216
    -          })
    
    1217
    -          .join(", ")}]`
    
    1204
    +        `TorConnect: Will load after bootstrap => [${uris.join(", ")}]`
    
    1218 1205
           );
    
    1219
    -      return redirectUrls;
    
    1206
    +      return uris.map(uri => this.getRedirectURL(uri));
    
    1220 1207
         },
    
    1221 1208
       };
    
    1222 1209
       return retval;