[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [Git][tpo/applications/tor-browser][tor-browser-115.10.0esr-13.5-1] 20 commits: fixup! Bug 40597: Implement TorSettings module



Title: GitLab

Pier Angelo Vendrame pushed to branch tor-browser-115.10.0esr-13.5-1 at The Tor Project / Applications / Tor Browser

Commits:

  • 3865ebab
    by Pier Angelo Vendrame at 2024-04-15T17:59:33+02:00
    fixup! Bug 40597: Implement TorSettings module
    
    Move TorSettings and TorLauncherUtil to lazy imnports.
    Also removed XPCOMUtils in favor of ChromeUtils.
    
  • d53805c2
    by Pier Angelo Vendrame at 2024-04-15T17:59:36+02:00
    fixup! Temporary changes to about:torconnect for Android.
    
  • 7720009e
    by Pier Angelo Vendrame at 2024-04-15T17:59:36+02:00
    fixup! Bug 40933: Add tor-launcher functionality
    
    Rename TorControlPort.sys.mjs's `TorError` to a less generic
    `TorProtocolError`.
    
  • bb516579
    by Pier Angelo Vendrame at 2024-04-15T17:59:37+02:00
    dropme! Bug 42247: Android helpers for the TorProvider
    
    Revert the changes to TorProvider*.sys.mjs to move them to the correct
    commit.
    
  • 76623561
    by Dan Ballard at 2024-04-15T17:59:37+02:00
    fixup! Bug 40933: Add tor-launcher functionality
    
    Bug 41187: Add support for tor logs in android integration
    
  • 8d41f191
    by Pier Angelo Vendrame at 2024-04-15T17:59:37+02:00
    fixup! Bug 40933: Add tor-launcher functionality
    
    Do not localize errors in TorProcess, but keep it only as a pure backend
    file. Moreover, the localized errors would be only shown in the console.
    Instead, report an error code to let them bubble up to the
    TorProviderBuilder, where we show them in the "Restart Tor" prompt.
    
  • 05bda694
    by Pier Angelo Vendrame at 2024-04-15T17:59:38+02:00
    fixup! Bug 27476: Implement about:torconnect captive portal within Tor Browser
    
    Formatted comments.
    
  • d783693d
    by Pier Angelo Vendrame at 2024-04-15T17:59:38+02:00
    fixup! Bug 40933: Add tor-launcher functionality
    
    Bug 42479: Remove localization from the backend files.
    
    Also, use an Error object when the bootstrap fail, in preparation to the
    removal of TorBootstrapRequest.
    
  • 7dc831bf
    by Pier Angelo Vendrame at 2024-04-15T17:59:38+02:00
    fixup! Add TorStrings module for localization
    
    Load some torlauncher strings to show in about:torconnect in
    TorStrings.sys.mjs.
    
    We could move them to torConnect.properties, but maybe we are still in
    time for moving all of them to Fluent, so I preferred reducing the
    number of migrations.
    
    Also, remove unused strings from torlauncher.properties.
    
  • 04fbc3dc
    by Pier Angelo Vendrame at 2024-04-15T17:59:39+02:00
    fixup! Bug 40597: Implement TorSettings module
    
    Bug 42479: Improve TorConnect error handling.
    
    To do so, also remove localized error messages.
    Use error codes, and let the frontend use the localized messages.
    
  • 00c53294
    by Pier Angelo Vendrame at 2024-04-15T17:59:39+02:00
    fixup! Bug 27476: Implement about:torconnect captive portal within Tor Browser
    
    Bug 42479: Improve TorConnect error handling.
    
    Consume the new error codes and transform them into localized error
    messages.
    
  • 13ca87b4
    by Pier Angelo Vendrame at 2024-04-15T17:59:39+02:00
    fixup! Bug 42247: Android helpers for the TorProvider
    
    Bug 42479: Improve TorConnect error handling.
    
    Pass the new TorConnect error codes to Android.
    
  • 1e2083d7
    by Pier Angelo Vendrame at 2024-04-15T17:59:40+02:00
    fixup! Bug 40933: Add tor-launcher functionality
    
    This partially reverts commit 34f7e83335cde6653d897717741c9c8d41f858b7.
    
    It removes the errorCode logic, and throws non-localized error
    messages.
    
    Also, it removes the no-longer used getFormattedLocalizedString.
    
  • 05516a28
    by Pier Angelo Vendrame at 2024-04-15T17:59:40+02:00
    fixup! Bug 40933: Add tor-launcher functionality
    
    Changed a few calls to #stop since this method now expects an Erro
    object.
    
    Do not redefine topics, import them from TorProviderBuilder.sys.mjs.
    
    Use lazy imports for our code.
    
  • 01d7d557
    by Pier Angelo Vendrame at 2024-04-15T17:59:40+02:00
    fixup! Bug 40597: Implement TorSettings module
    
    Various fixes to address tor-browser!968.
    
  • 02df5609
    by Pier Angelo Vendrame at 2024-04-15T17:59:41+02:00
    fixup! Bug 27476: Implement about:torconnect captive portal within Tor Browser
    
    Various fixes to address tor-browser!968.
    
  • 76ee8c58
    by Pier Angelo Vendrame at 2024-04-15T17:59:41+02:00
    fixup! Bug 42247: Android helpers for the TorProvider
    
    TorConnectTopics.BootstrapError is now just Error, and it passes
    directly the Error object.
    
  • 686fb7e7
    by henry at 2024-04-15T17:59:41+02:00
    fixup! Add TorStrings module for localization
    
    Drop unused strings.
  • ec7b6520
    by henry at 2024-04-15T17:59:42+02:00
    fixup! Bug 27476: Implement about:torconnect captive portal within Tor Browser
    
    Fix the offline error handler.
  • e162a17a
    by henry at 2024-04-15T17:59:42+02:00
    fixup! Bug 40597: Implement TorSettings module
    
    Remove an outdated comment.

12 changed files:

Changes:

  • mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java
    ... ... @@ -42,10 +42,10 @@ public class TorIntegrationAndroid implements BundleEventListener {
    42 42
         private static final String EVENT_TOR_STOP = "GeckoView:Tor:StopTor";
    
    43 43
         private static final String EVENT_MEEK_START = "GeckoView:Tor:StartMeek";
    
    44 44
         private static final String EVENT_MEEK_STOP = "GeckoView:Tor:StopMeek";
    
    45
    -    private static final String EVENT_BOOTSTRAP_STATE_CHANGED = "GeckoView:Tor:BootstrapStateChanged";
    
    45
    +    private static final String EVENT_CONNECT_STATE_CHANGED = "GeckoView:Tor:ConnectStateChanged";
    
    46
    +    private static final String EVENT_CONNECT_ERROR = "GeckoView:Tor:ConnectError";
    
    46 47
         private static final String EVENT_BOOTSTRAP_PROGRESS = "GeckoView:Tor:BootstrapProgress";
    
    47 48
         private static final String EVENT_BOOTSTRAP_COMPLETE = "GeckoView:Tor:BootstrapComplete";
    
    48
    -    private static final String EVENT_BOOTSTRAP_ERROR = "GeckoView:Tor:BootstrapError";
    
    49 49
         private static final String EVENT_TOR_LOGS = "GeckoView:Tor:Logs";
    
    50 50
         private static final String EVENT_SETTINGS_READY = "GeckoView:Tor:SettingsReady";
    
    51 51
         private static final String EVENT_SETTINGS_CHANGED = "GeckoView:Tor:SettingsChanged";
    
    ... ... @@ -115,10 +115,10 @@ public class TorIntegrationAndroid implements BundleEventListener {
    115 115
                             EVENT_MEEK_STOP,
    
    116 116
                             EVENT_SETTINGS_READY,
    
    117 117
                             EVENT_SETTINGS_CHANGED,
    
    118
    -                        EVENT_BOOTSTRAP_STATE_CHANGED,
    
    118
    +                        EVENT_CONNECT_STATE_CHANGED,
    
    119
    +                        EVENT_CONNECT_ERROR,
    
    119 120
                             EVENT_BOOTSTRAP_PROGRESS,
    
    120 121
                             EVENT_BOOTSTRAP_COMPLETE,
    
    121
    -                        EVENT_BOOTSTRAP_ERROR,
    
    122 122
                             EVENT_TOR_LOGS,
    
    123 123
                             EVENT_SETTINGS_OPEN);
    
    124 124
         }
    
    ... ... @@ -148,28 +148,29 @@ public class TorIntegrationAndroid implements BundleEventListener {
    148 148
                 } else {
    
    149 149
                     Log.w(TAG, "Ignoring a settings changed event that did not have the new settings.");
    
    150 150
                 }
    
    151
    -        } else if (EVENT_BOOTSTRAP_STATE_CHANGED.equals(event)) {
    
    151
    +        } else if (EVENT_CONNECT_STATE_CHANGED.equals(event)) {
    
    152 152
                 String state = message.getString("state");
    
    153 153
                 for (BootstrapStateChangeListener listener: mBootstrapStateListeners) {
    
    154 154
                     listener.onBootstrapStateChange(state);
    
    155 155
                 }
    
    156
    +        } else if (EVENT_CONNECT_ERROR.equals(event)) {
    
    157
    +            String code = message.getString("code");
    
    158
    +            String msg = message.getString("message");
    
    159
    +            String phase = message.getString("phase");
    
    160
    +            String reason = message.getString("reason");
    
    161
    +            for (BootstrapStateChangeListener listener: mBootstrapStateListeners) {
    
    162
    +                listener.onBootstrapError(code, msg, phase, reason);
    
    163
    +            }
    
    156 164
             } else if (EVENT_BOOTSTRAP_PROGRESS.equals(event)) {
    
    157 165
                 double progress = message.getDouble("progress");
    
    158
    -            String status = message.getString("status");
    
    159 166
                 boolean hasWarnings = message.getBoolean("hasWarnings");
    
    160 167
                 for (BootstrapStateChangeListener listener: mBootstrapStateListeners) {
    
    161
    -                listener.onBootstrapProgress(progress, status, hasWarnings);
    
    168
    +                listener.onBootstrapProgress(progress, hasWarnings);
    
    162 169
                 }
    
    163 170
             } else if (EVENT_BOOTSTRAP_COMPLETE.equals(event)) {
    
    164 171
                 for (BootstrapStateChangeListener listener: mBootstrapStateListeners) {
    
    165 172
                     listener.onBootstrapComplete();
    
    166 173
                 }
    
    167
    -        } else if (EVENT_BOOTSTRAP_ERROR.equals(event)) {
    
    168
    -            String msg = message.getString("message");
    
    169
    -            String details = message.getString("details");
    
    170
    -            for (BootstrapStateChangeListener listener: mBootstrapStateListeners) {
    
    171
    -                listener.onBootstrapError(msg, details);
    
    172
    -            }
    
    173 174
             } else if (EVENT_TOR_LOGS.equals(event)) {
    
    174 175
                 String msg = message.getString("message");
    
    175 176
                 String type = message.getString("logType");
    
    ... ... @@ -575,9 +576,9 @@ public class TorIntegrationAndroid implements BundleEventListener {
    575 576
     
    
    576 577
         public interface BootstrapStateChangeListener {
    
    577 578
             void onBootstrapStateChange(String state);
    
    578
    -        void onBootstrapProgress(double progress, String status, boolean hasWarnings);
    
    579
    +        void onBootstrapProgress(double progress, boolean hasWarnings);
    
    579 580
             void onBootstrapComplete();
    
    580
    -        void onBootstrapError(String message, String details);
    
    581
    +        void onBootstrapError(String code, String message, String phase, String reason);
    
    581 582
             void onSettingsRequested();
    
    582 583
         }
    
    583 584
     
    

  • toolkit/components/tor-launcher/TorBootstrapRequest.sys.mjs
    1 1
     import { setTimeout, clearTimeout } from "resource://gre/modules/Timer.sys.mjs";
    
    2 2
     
    
    3
    -import { TorProviderBuilder } from "resource://gre/modules/TorProviderBuilder.sys.mjs";
    
    4
    -import { TorLauncherUtil } from "resource://gre/modules/TorLauncherUtil.sys.mjs";
    
    5
    -
    
    6
    -/* tor-launcher observer topics */
    
    7
    -export const TorTopics = Object.freeze({
    
    8
    -  BootstrapStatus: "TorBootstrapStatus",
    
    9
    -  BootstrapError: "TorBootstrapError",
    
    10
    -  LogHasWarnOrErr: "TorLogHasWarnOrErr",
    
    3
    +const lazy = {};
    
    4
    +
    
    5
    +ChromeUtils.defineESModuleGetters(lazy, {
    
    6
    +  TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs",
    
    7
    +  TorProviderTopics: "resource://gre/modules/TorProviderBuilder.sys.mjs",
    
    11 8
     });
    
    12 9
     
    
    13 10
     // modeled after XMLHttpRequest
    
    14 11
     // nicely encapsulates the observer register/unregister logic
    
    12
    +// TODO: Remove this class, and move its logic inside the TorProvider.
    
    15 13
     export class TorBootstrapRequest {
    
    16 14
       // number of ms to wait before we abandon the bootstrap attempt
    
    17 15
       // a value of 0 implies we never wait
    
    ... ... @@ -20,7 +18,7 @@ export class TorBootstrapRequest {
    20 18
       // callbacks for bootstrap process status updates
    
    21 19
       onbootstrapstatus = (progress, status) => {};
    
    22 20
       onbootstrapcomplete = () => {};
    
    23
    -  onbootstraperror = (message, details) => {};
    
    21
    +  onbootstraperror = error => {};
    
    24 22
     
    
    25 23
       // internal resolve() method for bootstrap
    
    26 24
       #bootstrapPromiseResolve = null;
    
    ... ... @@ -30,10 +28,10 @@ export class TorBootstrapRequest {
    30 28
       observe(subject, topic, data) {
    
    31 29
         const obj = subject?.wrappedJSObject;
    
    32 30
         switch (topic) {
    
    33
    -      case TorTopics.BootstrapStatus: {
    
    31
    +      case lazy.TorProviderTopics.BootstrapStatus: {
    
    34 32
             const progress = obj.PROGRESS;
    
    35
    -        const status = TorLauncherUtil.getLocalizedBootstrapStatus(obj, "TAG");
    
    36 33
             if (this.onbootstrapstatus) {
    
    34
    +          const status = obj.TAG;
    
    37 35
               this.onbootstrapstatus(progress, status);
    
    38 36
             }
    
    39 37
             if (progress === 100) {
    
    ... ... @@ -47,9 +45,11 @@ export class TorBootstrapRequest {
    47 45
     
    
    48 46
             break;
    
    49 47
           }
    
    50
    -      case TorTopics.BootstrapError: {
    
    48
    +      case lazy.TorProviderTopics.BootstrapError: {
    
    51 49
             console.info("TorBootstrapRequest: observerd TorBootstrapError", obj);
    
    52
    -        this.#stop(obj?.message, obj?.details);
    
    50
    +        const error = new Error(obj.summary);
    
    51
    +        Object.assign(error, obj);
    
    52
    +        this.#stop(error);
    
    53 53
             break;
    
    54 54
           }
    
    55 55
         }
    
    ... ... @@ -65,17 +65,17 @@ export class TorBootstrapRequest {
    65 65
           this.#bootstrapPromiseResolve = resolve;
    
    66 66
     
    
    67 67
           // register ourselves to listen for bootstrap events
    
    68
    -      Services.obs.addObserver(this, TorTopics.BootstrapStatus);
    
    69
    -      Services.obs.addObserver(this, TorTopics.BootstrapError);
    
    68
    +      Services.obs.addObserver(this, lazy.TorProviderTopics.BootstrapStatus);
    
    69
    +      Services.obs.addObserver(this, lazy.TorProviderTopics.BootstrapError);
    
    70 70
     
    
    71 71
           // optionally cancel bootstrap after a given timeout
    
    72 72
           if (this.timeout > 0) {
    
    73
    -        this.#timeoutID = setTimeout(async () => {
    
    73
    +        this.#timeoutID = setTimeout(() => {
    
    74 74
               this.#timeoutID = null;
    
    75
    -          // TODO: Translate, if really used
    
    76
    -          await this.#stop(
    
    77
    -            "Tor Bootstrap process timed out",
    
    78
    -            `Bootstrap attempt abandoned after waiting ${this.timeout} ms`
    
    75
    +          this.#stop(
    
    76
    +            new Error(
    
    77
    +              `Bootstrap attempt abandoned after waiting ${this.timeout} ms`
    
    78
    +            )
    
    79 79
               );
    
    80 80
             }, this.timeout);
    
    81 81
           }
    
    ... ... @@ -83,15 +83,15 @@ export class TorBootstrapRequest {
    83 83
           // Wait for bootstrapping to begin and maybe handle error.
    
    84 84
           // Notice that we do not resolve the promise here in case of success, but
    
    85 85
           // we do it from the BootstrapStatus observer.
    
    86
    -      TorProviderBuilder.build()
    
    86
    +      lazy.TorProviderBuilder.build()
    
    87 87
             .then(provider => provider.connect())
    
    88 88
             .catch(err => {
    
    89
    -          this.#stop(err.message, err.torMessage);
    
    89
    +          this.#stop(err);
    
    90 90
             });
    
    91 91
         }).finally(() => {
    
    92 92
           // and remove ourselves once bootstrap is resolved
    
    93
    -      Services.obs.removeObserver(this, TorTopics.BootstrapStatus);
    
    94
    -      Services.obs.removeObserver(this, TorTopics.BootstrapError);
    
    93
    +      Services.obs.removeObserver(this, lazy.TorProviderTopics.BootstrapStatus);
    
    94
    +      Services.obs.removeObserver(this, lazy.TorProviderTopics.BootstrapError);
    
    95 95
           this.#bootstrapPromise = null;
    
    96 96
         });
    
    97 97
     
    
    ... ... @@ -103,7 +103,7 @@ export class TorBootstrapRequest {
    103 103
       }
    
    104 104
     
    
    105 105
       // Internal implementation. Do not use directly, but call cancel, instead.
    
    106
    -  async #stop(message, details) {
    
    106
    +  async #stop(error) {
    
    107 107
         // first stop our bootstrap timeout before handling the error
    
    108 108
         if (this.#timeoutID !== null) {
    
    109 109
           clearTimeout(this.#timeoutID);
    
    ... ... @@ -112,7 +112,7 @@ export class TorBootstrapRequest {
    112 112
     
    
    113 113
         let provider;
    
    114 114
         try {
    
    115
    -      provider = await TorProviderBuilder.build();
    
    115
    +      provider = await lazy.TorProviderBuilder.build();
    
    116 116
         } catch {
    
    117 117
           // This was probably the error that lead to stop in the first place.
    
    118 118
           // No need to continue propagating it.
    
    ... ... @@ -121,14 +121,13 @@ export class TorBootstrapRequest {
    121 121
           await provider?.stopBootstrap();
    
    122 122
         } catch (e) {
    
    123 123
           console.error("Failed to stop the bootstrap.", e);
    
    124
    -      if (!message) {
    
    125
    -        message = e.message;
    
    126
    -        details = "";
    
    124
    +      if (!error) {
    
    125
    +        error = e;
    
    127 126
           }
    
    128 127
         }
    
    129 128
     
    
    130
    -    if (this.onbootstraperror && message) {
    
    131
    -      this.onbootstraperror(message, details);
    
    129
    +    if (this.onbootstraperror && error) {
    
    130
    +      this.onbootstraperror(error);
    
    132 131
         }
    
    133 132
     
    
    134 133
         this.#bootstrapPromiseResolve(false);
    

  • toolkit/components/tor-launcher/TorControlPort.sys.mjs
    ... ... @@ -311,10 +311,10 @@ class AsyncSocket {
    311 311
      * @param {string} message The message to handle
    
    312 312
      */
    
    313 313
     
    
    314
    -class TorError extends Error {
    
    314
    +class TorProtocolError extends Error {
    
    315 315
       constructor(command, reply) {
    
    316 316
         super(`${command} -> ${reply}`);
    
    317
    -    this.name = "TorError";
    
    317
    +    this.name = "TorProtocolError";
    
    318 318
         const info = reply.match(/(?<code>\d{3})(?:\s(?<message>.+))?/);
    
    319 319
         this.torStatusCode = info.groups.code;
    
    320 320
         if (info.groups.message) {
    
    ... ... @@ -591,7 +591,7 @@ export class TorController {
    591 591
       async #sendCommandSimple(command) {
    
    592 592
         const reply = await this.#sendCommand(command);
    
    593 593
         if (!/^250 OK\s*$/i.test(reply)) {
    
    594
    -      throw new TorError(command, reply);
    
    594
    +      throw new TorProtocolError(command, reply);
    
    595 595
         }
    
    596 596
       }
    
    597 597
     
    
    ... ... @@ -672,7 +672,7 @@ export class TorController {
    672 672
           reply.match(/^250-([^=]+)=(.*)$/m) ||
    
    673 673
           reply.match(/^250\+([^=]+)=\r?\n(.*?)\r?\n^\.\r?\n^250 OK\s*$/ms);
    
    674 674
         if (!match || match[1] !== key) {
    
    675
    -      throw new TorError(cmd, reply);
    
    675
    +      throw new TorProtocolError(cmd, reply);
    
    676 676
         }
    
    677 677
         return match[2];
    
    678 678
       }
    
    ... ... @@ -784,7 +784,7 @@ export class TorController {
    784 784
           TorParsers.unescapeString(m[1])
    
    785 785
         );
    
    786 786
         if (!values.length) {
    
    787
    -      throw new TorError(cmd, reply);
    
    787
    +      throw new TorProtocolError(cmd, reply);
    
    788 788
         }
    
    789 789
         return values;
    
    790 790
       }
    
    ... ... @@ -896,7 +896,7 @@ export class TorController {
    896 896
         const message = await this.#sendCommand(cmd);
    
    897 897
         // Either `250-CLIENT`, or `250 OK` if no keys are available.
    
    898 898
         if (!message.startsWith("250")) {
    
    899
    -      throw new TorError(cmd, message);
    
    899
    +      throw new TorProtocolError(cmd, message);
    
    900 900
         }
    
    901 901
         const re =
    
    902 902
           /^250-CLIENT\s+(?<HSAddress>[A-Za-z2-7]+)\s+(?<KeyType>[^:]+):(?<PrivateKeyBlob>\S+)(?:\s(?<other>.+))?$/gim;
    
    ... ... @@ -936,7 +936,7 @@ export class TorController {
    936 936
         const reply = await this.#sendCommand(cmd);
    
    937 937
         const status = reply.substring(0, 3);
    
    938 938
         if (status !== "250" && status !== "251" && status !== "252") {
    
    939
    -      throw new TorError(cmd, reply);
    
    939
    +      throw new TorProtocolError(cmd, reply);
    
    940 940
         }
    
    941 941
       }
    
    942 942
     
    
    ... ... @@ -952,7 +952,7 @@ export class TorController {
    952 952
         const reply = await this.#sendCommand(cmd);
    
    953 953
         const status = reply.substring(0, 3);
    
    954 954
         if (status !== "250" && status !== "251") {
    
    955
    -      throw new TorError(cmd, reply);
    
    955
    +      throw new TorProtocolError(cmd, reply);
    
    956 956
         }
    
    957 957
       }
    
    958 958
     
    
    ... ... @@ -1085,6 +1085,7 @@ export class TorController {
    1085 1085
           );
    
    1086 1086
         }
    
    1087 1087
         const status = {
    
    1088
    +      // Type is actually StatusSeverity in the specifications.
    
    1088 1089
           TYPE: match[1],
    
    1089 1090
           ...this.#getKeyValues(match[2]),
    
    1090 1091
         };
    

  • toolkit/components/tor-launcher/TorLauncherUtil.sys.mjs
    ... ... @@ -417,70 +417,6 @@ export const TorLauncherUtil = Object.freeze({
    417 417
         return aStringName;
    
    418 418
       },
    
    419 419
     
    
    420
    -  // "torlauncher." is prepended to aStringName.
    
    421
    -  getFormattedLocalizedString(aStringName, aArray, aLen) {
    
    422
    -    if (!aStringName || !aArray) {
    
    423
    -      return aStringName;
    
    424
    -    }
    
    425
    -    try {
    
    426
    -      const key = kPropNamePrefix + aStringName;
    
    427
    -      return this._stringBundle.formatStringFromName(key, aArray, aLen);
    
    428
    -    } catch (e) {}
    
    429
    -    return aStringName;
    
    430
    -  },
    
    431
    -
    
    432
    -  getLocalizedBootstrapStatus(aStatusObj, aKeyword) {
    
    433
    -    if (!aStatusObj || !aKeyword) {
    
    434
    -      return "";
    
    435
    -    }
    
    436
    -
    
    437
    -    let result;
    
    438
    -    let fallbackStr;
    
    439
    -    if (aStatusObj[aKeyword]) {
    
    440
    -      let val = aStatusObj[aKeyword].toLowerCase();
    
    441
    -      let key;
    
    442
    -      if (aKeyword === "TAG") {
    
    443
    -        // The bootstrap status tags in tagMap below are used by Tor
    
    444
    -        // versions prior to 0.4.0.x. We map each one to the tag that will
    
    445
    -        // produce the localized string that is the best fit.
    
    446
    -        const tagMap = {
    
    447
    -          conn_dir: "conn",
    
    448
    -          handshake_dir: "onehop_create",
    
    449
    -          conn_or: "enough_dirinfo",
    
    450
    -          handshake_or: "ap_conn",
    
    451
    -        };
    
    452
    -        if (val in tagMap) {
    
    453
    -          val = tagMap[val];
    
    454
    -        }
    
    455
    -
    
    456
    -        key = "bootstrapStatus." + val;
    
    457
    -        fallbackStr = aStatusObj.SUMMARY;
    
    458
    -      } else if (aKeyword === "REASON") {
    
    459
    -        if (val === "connectreset") {
    
    460
    -          val = "connectrefused";
    
    461
    -        }
    
    462
    -
    
    463
    -        key = "bootstrapWarning." + val;
    
    464
    -        fallbackStr = aStatusObj.WARNING;
    
    465
    -      }
    
    466
    -
    
    467
    -      result = TorLauncherUtil.getLocalizedString(key);
    
    468
    -      if (result === key) {
    
    469
    -        result = undefined;
    
    470
    -      }
    
    471
    -    }
    
    472
    -
    
    473
    -    if (!result) {
    
    474
    -      result = fallbackStr;
    
    475
    -    }
    
    476
    -
    
    477
    -    if (aKeyword === "REASON" && aStatusObj.HOSTADDR) {
    
    478
    -      result += " - " + aStatusObj.HOSTADDR;
    
    479
    -    }
    
    480
    -
    
    481
    -    return result ? result : "";
    
    482
    -  },
    
    483
    -
    
    484 420
       /**
    
    485 421
        * Determine what kind of SOCKS port has been requested for this session or
    
    486 422
        * the browser has been configured for.
    

  • toolkit/components/tor-launcher/TorProcess.sys.mjs
    ... ... @@ -193,54 +193,54 @@ export class TorProcess {
    193 193
     
    
    194 194
       #makeArgs() {
    
    195 195
         this.#exeFile = lazy.TorLauncherUtil.getTorFile("tor", false);
    
    196
    +    if (!this.#exeFile) {
    
    197
    +      throw new Error("Could not find the tor binary.");
    
    198
    +    }
    
    196 199
         const torrcFile = lazy.TorLauncherUtil.getTorFile("torrc", true);
    
    200
    +    if (!torrcFile) {
    
    201
    +      // FIXME: Is this still a fatal error?
    
    202
    +      throw new Error("Could not find the torrc.");
    
    203
    +    }
    
    197 204
         // Get the Tor data directory first so it is created before we try to
    
    198 205
         // construct paths to files that will be inside it.
    
    199 206
         this.#dataDir = lazy.TorLauncherUtil.getTorFile("tordatadir", true);
    
    207
    +    if (!this.#dataDir) {
    
    208
    +      throw new Error("Could not find the tor data directory.");
    
    209
    +    }
    
    200 210
         const onionAuthDir = lazy.TorLauncherUtil.getTorFile(
    
    201 211
           "toronionauthdir",
    
    202 212
           true
    
    203 213
         );
    
    204
    -    let detailsKey;
    
    205
    -    if (!this.#exeFile) {
    
    206
    -      detailsKey = "tor_missing";
    
    207
    -    } else if (!torrcFile) {
    
    208
    -      detailsKey = "torrc_missing";
    
    209
    -    } else if (!this.#dataDir) {
    
    210
    -      detailsKey = "datadir_missing";
    
    211
    -    } else if (!onionAuthDir) {
    
    212
    -      detailsKey = "onionauthdir_missing";
    
    213
    -    }
    
    214
    -    if (detailsKey) {
    
    215
    -      const details = lazy.TorLauncherUtil.getLocalizedString(detailsKey);
    
    216
    -      const key = "unable_to_start_tor";
    
    217
    -      const err = lazy.TorLauncherUtil.getFormattedLocalizedString(
    
    218
    -        key,
    
    219
    -        [details],
    
    220
    -        1
    
    221
    -      );
    
    222
    -      throw new Error(err);
    
    214
    +    if (!onionAuthDir) {
    
    215
    +      throw new Error("Could not find the tor onion authentication directory.");
    
    223 216
         }
    
    224 217
     
    
    218
    +    this.#args = [];
    
    219
    +    this.#args.push("-f", torrcFile.path);
    
    220
    +    this.#args.push("DataDirectory", this.#dataDir.path);
    
    221
    +    this.#args.push("ClientOnionAuthDir", onionAuthDir.path);
    
    222
    +
    
    223
    +    // TODO: Create this starting from pt_config.json (tor-browser#42357).
    
    225 224
         const torrcDefaultsFile = lazy.TorLauncherUtil.getTorFile(
    
    226 225
           "torrc-defaults",
    
    227 226
           false
    
    228 227
         );
    
    229
    -    // The geoip and geoip6 files are in the same directory as torrc-defaults.
    
    230
    -    const geoipFile = torrcDefaultsFile.clone();
    
    231
    -    geoipFile.leafName = "geoip";
    
    232
    -    const geoip6File = torrcDefaultsFile.clone();
    
    233
    -    geoip6File.leafName = "geoip6";
    
    234
    -
    
    235
    -    this.#args = [];
    
    236 228
         if (torrcDefaultsFile) {
    
    237 229
           this.#args.push("--defaults-torrc", torrcDefaultsFile.path);
    
    230
    +      // The geoip and geoip6 files are in the same directory as torrc-defaults.
    
    231
    +      // TODO: Change TorFile to return the generic path to these files to make
    
    232
    +      // them independent from the torrc-defaults.
    
    233
    +      const geoipFile = torrcDefaultsFile.clone();
    
    234
    +      geoipFile.leafName = "geoip";
    
    235
    +      this.#args.push("GeoIPFile", geoipFile.path);
    
    236
    +      const geoip6File = torrcDefaultsFile.clone();
    
    237
    +      geoip6File.leafName = "geoip6";
    
    238
    +      this.#args.push("GeoIPv6File", geoip6File.path);
    
    239
    +    } else {
    
    240
    +      logger.warn(
    
    241
    +        "torrc-defaults was not found, some functionalities will be disabled."
    
    242
    +      );
    
    238 243
         }
    
    239
    -    this.#args.push("-f", torrcFile.path);
    
    240
    -    this.#args.push("DataDirectory", this.#dataDir.path);
    
    241
    -    this.#args.push("ClientOnionAuthDir", onionAuthDir.path);
    
    242
    -    this.#args.push("GeoIPFile", geoipFile.path);
    
    243
    -    this.#args.push("GeoIPv6File", geoip6File.path);
    
    244 244
       }
    
    245 245
     
    
    246 246
       /**
    

  • toolkit/components/tor-launcher/TorProvider.sys.mjs
    ... ... @@ -911,6 +911,7 @@ export class TorProvider {
    911 911
        * @param {object} status The status object
    
    912 912
        */
    
    913 913
       onBootstrapStatus(status) {
    
    914
    +    logger.debug("Received bootstrap status update", status);
    
    914 915
         this.#processBootstrapStatus(status, true);
    
    915 916
       }
    
    916 917
     
    
    ... ... @@ -939,6 +940,7 @@ export class TorProvider {
    939 940
     
    
    940 941
         this.#isBootstrapDone = false;
    
    941 942
     
    
    943
    +    // Can TYPE ever be ERR for STATUS_CLIENT?
    
    942 944
         if (
    
    943 945
           isNotification &&
    
    944 946
           statusObj.TYPE === "WARN" &&
    
    ... ... @@ -959,20 +961,7 @@ export class TorProvider {
    959 961
         } catch (e) {
    
    960 962
           logger.warn(`Cannot set ${Preferences.PromptAtStartup}`, e);
    
    961 963
         }
    
    962
    -    // TODO: Move l10n to the above layers?
    
    963
    -    const phase = TorLauncherUtil.getLocalizedBootstrapStatus(statusObj, "TAG");
    
    964
    -    const reason = TorLauncherUtil.getLocalizedBootstrapStatus(
    
    965
    -      statusObj,
    
    966
    -      "REASON"
    
    967
    -    );
    
    968
    -    const details = TorLauncherUtil.getFormattedLocalizedString(
    
    969
    -      "tor_bootstrap_failed_details",
    
    970
    -      [phase, reason],
    
    971
    -      2
    
    972
    -    );
    
    973
    -    logger.error(
    
    974
    -      `Tor bootstrap error: [${statusObj.TAG}/${statusObj.REASON}] ${details}`
    
    975
    -    );
    
    964
    +    logger.error("Tor bootstrap error", statusObj);
    
    976 965
     
    
    977 966
         if (
    
    978 967
           statusObj.TAG !== this.#lastWarning.phase ||
    
    ... ... @@ -981,11 +970,19 @@ export class TorProvider {
    981 970
           this.#lastWarning.phase = statusObj.TAG;
    
    982 971
           this.#lastWarning.reason = statusObj.REASON;
    
    983 972
     
    
    984
    -      const message = TorLauncherUtil.getLocalizedString(
    
    985
    -        "tor_bootstrap_failed"
    
    986
    -      );
    
    973
    +      // FIXME: currently, this is observed only by TorBoostrapRequest.
    
    974
    +      // We should remove that class, and use an async method to do the
    
    975
    +      // bootstrap here.
    
    976
    +      // At that point, the lastWarning mechanism will probably not be necessary
    
    977
    +      // anymore, since the first error eligible for notification will as a
    
    978
    +      // matter of fact cancel the bootstrap.
    
    987 979
           Services.obs.notifyObservers(
    
    988
    -        { message, details },
    
    980
    +        {
    
    981
    +          phase: statusObj.TAG,
    
    982
    +          reason: statusObj.REASON,
    
    983
    +          summary: statusObj.SUMMARY,
    
    984
    +          warning: statusObj.WARNING,
    
    985
    +        },
    
    989 986
             TorProviderTopics.BootstrapError
    
    990 987
           );
    
    991 988
         }
    

  • toolkit/components/torconnect/TorConnectParent.sys.mjs
    ... ... @@ -37,10 +37,9 @@ export class TorConnectParent extends JSWindowActorParent {
    37 37
           State: TorConnect.state,
    
    38 38
           StateChanged: false,
    
    39 39
           PreviousState: TorConnectState.Initial,
    
    40
    -      ErrorMessage: TorConnect.errorMessage,
    
    40
    +      ErrorCode: TorConnect.errorCode,
    
    41 41
           ErrorDetails: TorConnect.errorDetails,
    
    42 42
           BootstrapProgress: TorConnect.bootstrapProgress,
    
    43
    -      BootstrapStatus: TorConnect.bootstrapStatus,
    
    44 43
           InternetStatus: TorConnect.internetStatus,
    
    45 44
           DetectedLocation: TorConnect.detectedLocation,
    
    46 45
           ShowViewLog: TorConnect.logHasWarningOrError,
    
    ... ... @@ -59,36 +58,36 @@ export class TorConnectParent extends JSWindowActorParent {
    59 58
           this.state.QuickStartEnabled = false;
    
    60 59
         }
    
    61 60
     
    
    62
    -    // JSWindowActiveParent derived objects cannot observe directly, so create a member
    
    63
    -    // object to do our observing for us
    
    61
    +    // JSWindowActiveParent derived objects cannot observe directly, so create a
    
    62
    +    // member object to do our observing for us.
    
    64 63
         //
    
    65
    -    // This object converts the various lifecycle events from the TorConnect module, and
    
    66
    -    // maintains a state object which we pass down to our about:torconnect page, which uses
    
    67
    -    // the state object to update its UI
    
    64
    +    // This object converts the various lifecycle events from the TorConnect
    
    65
    +    // module, and maintains a state object which we pass down to our
    
    66
    +    // about:torconnect page, which uses the state object to update its UI.
    
    68 67
         this.torConnectObserver = {
    
    69 68
           observe(aSubject, aTopic, aData) {
    
    70 69
             let obj = aSubject?.wrappedJSObject;
    
    71 70
     
    
    72
    -        // update our state struct based on received torconnect topics and forward on
    
    73
    -        // to aboutTorConnect.js
    
    71
    +        // Update our state struct based on received torconnect topics and
    
    72
    +        // forward on to aboutTorConnect.js.
    
    74 73
             self.state.StateChanged = false;
    
    75 74
             switch (aTopic) {
    
    76 75
               case TorConnectTopics.StateChange: {
    
    77 76
                 self.state.PreviousState = self.state.State;
    
    78 77
                 self.state.State = obj.state;
    
    79 78
                 self.state.StateChanged = true;
    
    80
    -
    
    81
    -            // clear any previous error information if we are bootstrapping
    
    79
    +            // Clear any previous error information if we are bootstrapping.
    
    82 80
                 if (self.state.State === TorConnectState.Bootstrapping) {
    
    83
    -              self.state.ErrorMessage = null;
    
    81
    +              self.state.ErrorCode = null;
    
    84 82
                   self.state.ErrorDetails = null;
    
    85 83
                 }
    
    84
    +            self.state.BootstrapProgress = TorConnect.bootstrapProgress;
    
    85
    +            self.state.ShowViewLog = TorConnect.logHasWarningOrError;
    
    86 86
                 self.state.HasEverFailed = TorConnect.hasEverFailed;
    
    87 87
                 break;
    
    88 88
               }
    
    89 89
               case TorConnectTopics.BootstrapProgress: {
    
    90 90
                 self.state.BootstrapProgress = obj.progress;
    
    91
    -            self.state.BootstrapStatus = obj.status;
    
    92 91
                 self.state.ShowViewLog = obj.hasWarnings;
    
    93 92
                 break;
    
    94 93
               }
    
    ... ... @@ -96,9 +95,9 @@ export class TorConnectParent extends JSWindowActorParent {
    96 95
                 // noop
    
    97 96
                 break;
    
    98 97
               }
    
    99
    -          case TorConnectTopics.BootstrapError: {
    
    100
    -            self.state.ErrorMessage = obj.message;
    
    101
    -            self.state.ErrorDetails = obj.details;
    
    98
    +          case TorConnectTopics.Error: {
    
    99
    +            self.state.ErrorCode = obj.code;
    
    100
    +            self.state.ErrorDetails = obj;
    
    102 101
                 self.state.InternetStatus = TorConnect.internetStatus;
    
    103 102
                 self.state.DetectedLocation = TorConnect.detectedLocation;
    
    104 103
                 self.state.ShowViewLog = true;
    
    ... ... @@ -134,7 +133,7 @@ export class TorConnectParent extends JSWindowActorParent {
    134 133
           },
    
    135 134
         };
    
    136 135
     
    
    137
    -    // observe all of the torconnect:.* topics
    
    136
    +    // Observe all of the torconnect:.* topics.
    
    138 137
         for (const key in TorConnectTopics) {
    
    139 138
           const topic = TorConnectTopics[key];
    
    140 139
           Services.obs.addObserver(this.torConnectObserver, topic);
    
    ... ... @@ -158,7 +157,7 @@ export class TorConnectParent extends JSWindowActorParent {
    158 157
       }
    
    159 158
     
    
    160 159
       willDestroy() {
    
    161
    -    // stop observing all of our torconnect:.* topics
    
    160
    +    // Stop observing all of our torconnect:.* topics.
    
    162 161
         for (const key in TorConnectTopics) {
    
    163 162
           const topic = TorConnectTopics[key];
    
    164 163
           Services.obs.removeObserver(this.torConnectObserver, topic);
    
    ... ... @@ -213,7 +212,8 @@ export class TorConnectParent extends JSWindowActorParent {
    213 212
             Services.obs.notifyObservers(message.data, BroadcastTopic);
    
    214 213
             break;
    
    215 214
           case "torconnect:get-init-args":
    
    216
    -        // called on AboutTorConnect.init(), pass down all state data it needs to init
    
    215
    +        // Called on AboutTorConnect.init(), pass down all state data it needs
    
    216
    +        // to init.
    
    217 217
     
    
    218 218
             // pretend this is a state transition on init
    
    219 219
             // so we always get fresh UI
    

  • toolkit/components/torconnect/content/aboutTorConnect.js
    ... ... @@ -347,6 +347,59 @@ class AboutTorConnect {
    347 347
         this.elements.breadcrumbContainer.classList.add("hidden");
    
    348 348
       }
    
    349 349
     
    
    350
    +  getLocalizedStatus(status) {
    
    351
    +    const aliases = {
    
    352
    +      conn_dir: "conn",
    
    353
    +      handshake_dir: "onehop_create",
    
    354
    +      conn_or: "enough_dirinfo",
    
    355
    +      handshake_or: "ap_conn",
    
    356
    +    };
    
    357
    +    if (status in aliases) {
    
    358
    +      status = aliases[status];
    
    359
    +    }
    
    360
    +    return TorStrings.torConnect.bootstrapStatus[status] ?? status;
    
    361
    +  }
    
    362
    +
    
    363
    +  getMaybeLocalizedError(state) {
    
    364
    +    if (!state?.ErrorCode) {
    
    365
    +      return "";
    
    366
    +    }
    
    367
    +    switch (state.ErrorCode) {
    
    368
    +      case "Offline":
    
    369
    +        return TorStrings.torConnect.offline;
    
    370
    +      case "BootstrapError": {
    
    371
    +        const details = state.ErrorDetails?.cause;
    
    372
    +        if (!details?.phase || !details?.reason) {
    
    373
    +          return TorStrings.torConnect.torBootstrapFailed;
    
    374
    +        }
    
    375
    +        let status = this.getLocalizedStatus(details.phase);
    
    376
    +        const reason =
    
    377
    +          TorStrings.torConnect.bootstrapWarning[details.reason] ??
    
    378
    +          details.reason;
    
    379
    +        return TorStrings.torConnect.bootstrapFailedDetails
    
    380
    +          .replace("%1$S", status)
    
    381
    +          .replace("%2$S", reason);
    
    382
    +      }
    
    383
    +      case "CannotDetermineCountry":
    
    384
    +        return TorStrings.torConnect.cannotDetermineCountry;
    
    385
    +      case "NoSettingsForCountry":
    
    386
    +        return TorStrings.torConnect.noSettingsForCountry;
    
    387
    +      case "AllSettingsFailed":
    
    388
    +        return TorStrings.torConnect.autoBootstrappingAllFailed;
    
    389
    +      case "ExternaError":
    
    390
    +        // A standard JS error, or something for which we do probably do not
    
    391
    +        // have a translation. Returning the original message is the best we can
    
    392
    +        // do.
    
    393
    +        return state.ErrorDetails.message;
    
    394
    +      default:
    
    395
    +        console.warn(
    
    396
    +          `Unknown error code: ${state.ErrorCode}`,
    
    397
    +          state.ErrorDetails
    
    398
    +        );
    
    399
    +        return state.ErrorDetails?.message ?? state.ErrorCode;
    
    400
    +    }
    
    401
    +  }
    
    402
    +
    
    350 403
       /*
    
    351 404
       These methods update the UI based on the current TorConnect state
    
    352 405
       */
    
    ... ... @@ -505,10 +558,10 @@ class AboutTorConnect {
    505 558
         }
    
    506 559
       }
    
    507 560
     
    
    508
    -  showOffline(error) {
    
    561
    +  showOffline(state) {
    
    509 562
         this.setTitle(TorStrings.torConnect.noInternet, "offline");
    
    510 563
         this.setLongText(TorStrings.torConnect.noInternetDescription);
    
    511
    -    this.setProgress(error, false);
    
    564
    +    this.setProgress(this.getMaybeLocalizedError(state), false);
    
    512 565
         this.setBreadcrumbsStatus(
    
    513 566
           BreadcrumbStatus.Default,
    
    514 567
           BreadcrumbStatus.Active,
    
    ... ... @@ -524,7 +577,7 @@ class AboutTorConnect {
    524 577
       showConnectionAssistant(state) {
    
    525 578
         this.setTitle(TorStrings.torConnect.couldNotConnect, "assist");
    
    526 579
         this.showConfigureConnectionLink(TorStrings.torConnect.assistDescription);
    
    527
    -    this.setProgress(state?.ErrorDetails, false);
    
    580
    +    this.setProgress(this.getMaybeLocalizedError(state), false);
    
    528 581
         this.setBreadcrumbsStatus(
    
    529 582
           BreadcrumbStatus.Default,
    
    530 583
           BreadcrumbStatus.Active,
    
    ... ... @@ -544,7 +597,7 @@ class AboutTorConnect {
    544 597
         this.showConfigureConnectionLink(
    
    545 598
           TorStrings.torConnect.errorLocationDescription
    
    546 599
         );
    
    547
    -    this.setProgress(state.ErrorMessage, false);
    
    600
    +    this.setProgress(TorStrings.torConnect.cannotDetermineCountry, false);
    
    548 601
         this.setBreadcrumbsStatus(
    
    549 602
           BreadcrumbStatus.Default,
    
    550 603
           BreadcrumbStatus.Active,
    
    ... ... @@ -564,7 +617,7 @@ class AboutTorConnect {
    564 617
         this.showConfigureConnectionLink(
    
    565 618
           TorStrings.torConnect.isLocationCorrectDescription
    
    566 619
         );
    
    567
    -    this.setProgress(state.ErrorMessage, false);
    
    620
    +    this.setProgress(this.getMaybeLocalizedError(state), false);
    
    568 621
         this.setBreadcrumbsStatus(
    
    569 622
           BreadcrumbStatus.Default,
    
    570 623
           BreadcrumbStatus.Default,
    
    ... ... @@ -582,7 +635,7 @@ class AboutTorConnect {
    582 635
       showFinalError(state) {
    
    583 636
         this.setTitle(TorStrings.torConnect.finalError, "final");
    
    584 637
         this.setLongText(TorStrings.torConnect.finalErrorDescription);
    
    585
    -    this.setProgress(state ? state.ErrorDetails : "", false);
    
    638
    +    this.setProgress(this.getMaybeLocalizedError(state), false);
    
    586 639
         this.setBreadcrumbsStatus(
    
    587 640
           BreadcrumbStatus.Default,
    
    588 641
           BreadcrumbStatus.Default,
    
    ... ... @@ -666,7 +719,7 @@ class AboutTorConnect {
    666 719
       }
    
    667 720
     
    
    668 721
       initElements(direction) {
    
    669
    -    const isAndroid = navigator.userAgent.indexOf("Android") !== -1;
    
    722
    +    const isAndroid = navigator.userAgent.includes("Android");
    
    670 723
         document.body.classList.toggle("android", isAndroid);
    
    671 724
     
    
    672 725
         document.documentElement.setAttribute("dir", direction);
    

  • toolkit/modules/TorAndroidIntegration.sys.mjs
    ... ... @@ -29,10 +29,10 @@ const logger = new ConsoleAPI({
    29 29
     const EmittedEvents = Object.freeze({
    
    30 30
       settingsReady: "GeckoView:Tor:SettingsReady",
    
    31 31
       settingsChanged: "GeckoView:Tor:SettingsChanged",
    
    32
    -  bootstrapStateChanged: "GeckoView:Tor:BootstrapStateChanged",
    
    32
    +  connectStateChanged: "GeckoView:Tor:ConnectStateChanged",
    
    33
    +  connectError: "GeckoView:Tor:ConnectError",
    
    33 34
       bootstrapProgress: "GeckoView:Tor:BootstrapProgress",
    
    34 35
       bootstrapComplete: "GeckoView:Tor:BootstrapComplete",
    
    35
    -  bootstrapError: "GeckoView:Tor:BootstrapError",
    
    36 36
       torLogs: "GeckoView:Tor:Logs",
    
    37 37
     });
    
    38 38
     
    
    ... ... @@ -98,15 +98,14 @@ class TorAndroidIntegrationImpl {
    98 98
             break;
    
    99 99
           case lazy.TorConnectTopics.StateChange:
    
    100 100
             lazy.EventDispatcher.instance.sendRequest({
    
    101
    -          type: EmittedEvents.bootstrapStateChanged,
    
    101
    +          type: EmittedEvents.connectStateChanged,
    
    102 102
               state: subj.wrappedJSObject.state ?? "",
    
    103 103
             });
    
    104 104
             break;
    
    105 105
           case lazy.TorConnectTopics.BootstrapProgress:
    
    106 106
             lazy.EventDispatcher.instance.sendRequest({
    
    107 107
               type: EmittedEvents.bootstrapProgress,
    
    108
    -          progress: subj.wrappedJSObject.progress ?? "",
    
    109
    -          status: subj.wrappedJSObject.status ?? 0,
    
    108
    +          progress: subj.wrappedJSObject.progress ?? 0,
    
    110 109
               hasWarnings: subj.wrappedJSObject.hasWarnings ?? false,
    
    111 110
             });
    
    112 111
             break;
    
    ... ... @@ -115,11 +114,13 @@ class TorAndroidIntegrationImpl {
    115 114
               type: EmittedEvents.bootstrapComplete,
    
    116 115
             });
    
    117 116
             break;
    
    118
    -      case lazy.TorConnectTopics.BootstrapError:
    
    117
    +      case lazy.TorConnectTopics.Error:
    
    119 118
             lazy.EventDispatcher.instance.sendRequest({
    
    120
    -          type: EmittedEvents.bootstrapError,
    
    119
    +          type: EmittedEvents.connectError,
    
    120
    +          code: subj.wrappedJSObject.code ?? "",
    
    121 121
               message: subj.wrappedJSObject.message ?? "",
    
    122
    -          details: subj.wrappedJSObject.details ?? "",
    
    122
    +          phase: subj.wrappedJSObject.cause?.phase ?? "",
    
    123
    +          reason: subj.wrappedJSObject.cause?.reason ?? "",
    
    123 124
             });
    
    124 125
             break;
    
    125 126
           case lazy.TorProviderTopics.TorLog:
    

  • toolkit/modules/TorConnect.sys.mjs
    ... ... @@ -2,7 +2,6 @@
    2 2
      * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3 3
      * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    
    4 4
     
    
    5
    -import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
    
    6 5
     import { setTimeout, clearTimeout } from "resource://gre/modules/Timer.sys.mjs";
    
    7 6
     
    
    8 7
     const lazy = {};
    
    ... ... @@ -13,6 +12,9 @@ ChromeUtils.defineESModuleGetters(lazy, {
    13 12
       MoatRPC: "resource://gre/modules/Moat.sys.mjs",
    
    14 13
       TorBootstrapRequest: "resource://gre/modules/TorBootstrapRequest.sys.mjs",
    
    15 14
       TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs",
    
    15
    +  TorProviderTopics: "resource://gre/modules/TorProviderBuilder.sys.mjs",
    
    16
    +  TorLauncherUtil: "resource://gre/modules/TorLauncherUtil.sys.mjs",
    
    17
    +  TorSettings: "resource://gre/modules/TorSettings.sys.mjs",
    
    16 18
     });
    
    17 19
     
    
    18 20
     // TODO: Should we move this to the about:torconnect actor?
    
    ... ... @@ -22,16 +24,6 @@ ChromeUtils.defineModuleGetter(
    22 24
       "resource:///modules/BrowserWindowTracker.jsm"
    
    23 25
     );
    
    24 26
     
    
    25
    -import { TorLauncherUtil } from "resource://gre/modules/TorLauncherUtil.sys.mjs";
    
    26
    -import { TorSettings } from "resource://gre/modules/TorSettings.sys.mjs";
    
    27
    -
    
    28
    -import { TorStrings } from "resource://gre/modules/TorStrings.sys.mjs";
    
    29
    -
    
    30
    -const TorTopics = Object.freeze({
    
    31
    -  LogHasWarnOrErr: "TorLogHasWarnOrErr",
    
    32
    -  ProcessExited: "TorProcessExited",
    
    33
    -});
    
    34
    -
    
    35 27
     /* Relevant prefs used by tor-launcher */
    
    36 28
     const TorLauncherPrefs = Object.freeze({
    
    37 29
       prompt_at_startup: "extensions.torlauncher.prompt_at_startup",
    
    ... ... @@ -60,7 +52,23 @@ export const TorConnectState = Object.freeze({
    60 52
       Disabled: "Disabled",
    
    61 53
     });
    
    62 54
     
    
    63
    -XPCOMUtils.defineLazyGetter(
    
    55
    +export class TorConnectError extends Error {
    
    56
    +  static Offline = "Offline";
    
    57
    +  static BootstrapError = "BootstrapError";
    
    58
    +  static CannotDetermineCountry = "CannotDetermineCountry";
    
    59
    +  static NoSettingsForCountry = "NoSettingsForCountry";
    
    60
    +  static AllSettingsFailed = "AllSettingsFailed";
    
    61
    +  static ExternalError = "ExternalError";
    
    62
    +
    
    63
    +  constructor(code, cause) {
    
    64
    +    super(cause?.message ?? `TorConnectError: ${code}`, cause ? { cause } : {});
    
    65
    +    this.name = "TorConnectError";
    
    66
    +    this.code = code;
    
    67
    +  }
    
    68
    +}
    
    69
    +Object.freeze(TorConnectError);
    
    70
    +
    
    71
    +ChromeUtils.defineLazyGetter(
    
    64 72
       lazy,
    
    65 73
       "logger",
    
    66 74
       () =>
    
    ... ... @@ -122,7 +130,7 @@ export const TorConnectTopics = Object.freeze({
    122 130
       StateChange: "torconnect:state-change",
    
    123 131
       BootstrapProgress: "torconnect:bootstrap-progress",
    
    124 132
       BootstrapComplete: "torconnect:bootstrap-complete",
    
    125
    -  BootstrapError: "torconnect:bootstrap-error",
    
    133
    +  Error: "torconnect:error",
    
    126 134
     });
    
    127 135
     
    
    128 136
     // The StateCallback is the base class to implement the various states.
    
    ... ... @@ -173,7 +181,7 @@ class StateCallback {
    173 181
             `${this.#state}'s run threw, transitioning to the Error state.`,
    
    174 182
             err
    
    175 183
           );
    
    176
    -      this.changeState(TorConnectState.Error, err?.message, err?.details);
    
    184
    +      this.changeState(TorConnectState.Error, err);
    
    177 185
         }
    
    178 186
       }
    
    179 187
     
    
    ... ... @@ -263,14 +271,13 @@ class ConfiguringState extends StateCallback {
    263 271
       }
    
    264 272
     
    
    265 273
       run() {
    
    266
    -    // The configuring state does not do anything.
    
    274
    +    TorConnect._bootstrapProgress = 0;
    
    267 275
       }
    
    268 276
     }
    
    269 277
     
    
    270 278
     class BootstrappingState extends StateCallback {
    
    271 279
       #bootstrap = null;
    
    272
    -  #bootstrapError = "";
    
    273
    -  #bootstrapErrorDetails = "";
    
    280
    +  #bootstrapError = null;
    
    274 281
       #internetTest = null;
    
    275 282
       #cancelled = false;
    
    276 283
     
    
    ... ... @@ -291,13 +298,13 @@ class BootstrappingState extends StateCallback {
    291 298
     
    
    292 299
         this.#bootstrap = new lazy.TorBootstrapRequest();
    
    293 300
         this.#bootstrap.onbootstrapstatus = (progress, status) => {
    
    294
    -      TorConnect._updateBootstrapStatus(progress, status);
    
    301
    +      TorConnect._updateBootstrapProgress(progress, status);
    
    295 302
         };
    
    296 303
         this.#bootstrap.onbootstrapcomplete = () => {
    
    297 304
           this.#internetTest.cancel();
    
    298 305
           this.changeState(TorConnectState.Bootstrapped);
    
    299 306
         };
    
    300
    -    this.#bootstrap.onbootstraperror = (message, details) => {
    
    307
    +    this.#bootstrap.onbootstraperror = error => {
    
    301 308
           if (this.#cancelled) {
    
    302 309
             // We ignore this error since it occurred after cancelling (by the
    
    303 310
             // user). We assume the error is just a side effect of the cancelling.
    
    ... ... @@ -305,13 +312,12 @@ class BootstrappingState extends StateCallback {
    305 312
             // "Building circuits: Establishing a Tor circuit failed".
    
    306 313
             // TODO: Maybe move this logic deeper in the process to know when to
    
    307 314
             // filter out such errors triggered by cancelling.
    
    308
    -        lazy.logger.warn(`Post-cancel error => ${message}; ${details}`);
    
    315
    +        lazy.logger.warn("Post-cancel error.", error);
    
    309 316
             return;
    
    310 317
           }
    
    311 318
           // We have to wait for the Internet test to finish before sending the
    
    312 319
           // bootstrap error
    
    313
    -      this.#bootstrapError = message;
    
    314
    -      this.#bootstrapErrorDetails = details;
    
    320
    +      this.#bootstrapError = error;
    
    315 321
           this.#maybeTransitionToError();
    
    316 322
         };
    
    317 323
     
    
    ... ... @@ -352,22 +358,23 @@ class BootstrappingState extends StateCallback {
    352 358
         // Do not transition to the offline error until we are sure that also the
    
    353 359
         // bootstrap failed, in case Moat is down but the bootstrap can proceed
    
    354 360
         // anyway.
    
    355
    -    if (this.#bootstrapError === "") {
    
    361
    +    if (!this.#bootstrapError) {
    
    356 362
           return;
    
    357 363
         }
    
    358 364
         if (this.#internetTest.status === InternetStatus.Offline) {
    
    359 365
           this.changeState(
    
    360 366
             TorConnectState.Error,
    
    361
    -        TorStrings.torConnect.offline,
    
    362
    -        ""
    
    367
    +        new TorConnectError(TorConnectError.Offline)
    
    363 368
           );
    
    364 369
         } else {
    
    365 370
           // Give priority to the bootstrap error, in case the Internet test fails
    
    366 371
           TorConnect._hasBootstrapEverFailed = true;
    
    367 372
           this.changeState(
    
    368 373
             TorConnectState.Error,
    
    369
    -        this.#bootstrapError,
    
    370
    -        this.#bootstrapErrorDetails
    
    374
    +        new TorConnectError(
    
    375
    +          TorConnectError.BootstrapError,
    
    376
    +          this.#bootstrapError
    
    377
    +        )
    
    371 378
           );
    
    372 379
         }
    
    373 380
       }
    
    ... ... @@ -393,10 +400,12 @@ class BootstrappingState extends StateCallback {
    393 400
           TorConnect._detectedLocation =
    
    394 401
             codes[Math.floor(Math.random() * codes.length)];
    
    395 402
         }
    
    403
    +    const err = new Error("Censorship simulation");
    
    404
    +    err.phase = "conn";
    
    405
    +    err.reason = "noroute";
    
    396 406
         this.changeState(
    
    397 407
           TorConnectState.Error,
    
    398
    -      "Bootstrap failed (for debugging purposes)",
    
    399
    -      "Error: Censorship simulation"
    
    408
    +      new TorConnectError(TorConnectError.BootstrapError, err)
    
    400 409
         );
    
    401 410
         return true;
    
    402 411
       }
    
    ... ... @@ -461,8 +470,7 @@ class AutoBootstrappingState extends StateCallback {
    461 470
           if (!this.transitioning) {
    
    462 471
             this.changeState(
    
    463 472
               TorConnectState.Error,
    
    464
    -          "Error: censorship simulation",
    
    465
    -          ""
    
    473
    +          new TorConnectError(TorConnectError.AllSettingsFailed)
    
    466 474
             );
    
    467 475
           }
    
    468 476
           return true;
    
    ... ... @@ -475,8 +483,7 @@ class AutoBootstrappingState extends StateCallback {
    475 483
           if (!this.transitioning) {
    
    476 484
             this.changeState(
    
    477 485
               TorConnectState.Error,
    
    478
    -          "Error: Severe Censorship simulation",
    
    479
    -          ""
    
    486
    +          new TorConnectError(TorConnectError.CannotDetermineCountry)
    
    480 487
             );
    
    481 488
           }
    
    482 489
           return true;
    
    ... ... @@ -507,7 +514,7 @@ class AutoBootstrappingState extends StateCallback {
    507 514
         // them.
    
    508 515
         const maybeSettings = await Promise.race([
    
    509 516
           this.#moat.circumvention_settings(
    
    510
    -        [...TorSettings.builtinBridgeTypes, "vanilla"],
    
    517
    +        [...lazy.TorSettings.builtinBridgeTypes, "vanilla"],
    
    511 518
             countryCode
    
    512 519
           ),
    
    513 520
           // This might set maybeSettings to undefined.
    
    ... ... @@ -523,7 +530,7 @@ class AutoBootstrappingState extends StateCallback {
    523 530
           // Keep consistency with the other call.
    
    524 531
           this.#settings = await Promise.race([
    
    525 532
             this.#moat.circumvention_defaults([
    
    526
    -          ...TorSettings.builtinBridgeTypes,
    
    533
    +          ...lazy.TorSettings.builtinBridgeTypes,
    
    527 534
               "vanilla",
    
    528 535
             ]),
    
    529 536
             // This might set this.#settings to undefined.
    
    ... ... @@ -532,22 +539,12 @@ class AutoBootstrappingState extends StateCallback {
    532 539
         }
    
    533 540
     
    
    534 541
         if (!this.#settings?.length && !this.transitioning) {
    
    535
    -      // Both localized and fallback have, we can just throw to transition to
    
    536
    -      // the error state (but only if we aren't already transitioning).
    
    537
    -      // TODO: Let the UI layer localize the strings.
    
    538
    -
    
    539 542
           if (!TorConnect._detectedLocation) {
    
    540 543
             // unable to determine country
    
    541
    -        this.#throwError(
    
    542
    -          TorStrings.torConnect.autoBootstrappingFailed,
    
    543
    -          TorStrings.torConnect.cannotDetermineCountry
    
    544
    -        );
    
    544
    +        throw new TorConnectError(TorConnectError.CannotDetermineCountry);
    
    545 545
           } else {
    
    546 546
             // no settings available for country
    
    547
    -        this.#throwError(
    
    548
    -          TorStrings.torConnect.autoBootstrappingFailed,
    
    549
    -          TorStrings.torConnect.noSettingsForCountry
    
    550
    -        );
    
    547
    +        throw new TorConnectError(TorConnectError.NoSettingsForCountry);
    
    551 548
           }
    
    552 549
         }
    
    553 550
       }
    
    ... ... @@ -585,17 +582,17 @@ class AutoBootstrappingState extends StateCallback {
    585 582
           // We need to merge with old settings, in case the user is using a proxy
    
    586 583
           // or is behind a firewall.
    
    587 584
           await provider.writeSettings({
    
    588
    -        ...TorSettings.getSettings(),
    
    585
    +        ...lazy.TorSettings.getSettings(),
    
    589 586
             ...currentSetting,
    
    590 587
           });
    
    591 588
     
    
    592 589
           // Build out our bootstrap request.
    
    593 590
           const bootstrap = new lazy.TorBootstrapRequest();
    
    594 591
           bootstrap.onbootstrapstatus = (progress, status) => {
    
    595
    -        TorConnect._updateBootstrapStatus(progress, status);
    
    592
    +        TorConnect._updateBootstrapProgress(progress, status);
    
    596 593
           };
    
    597
    -      bootstrap.onbootstraperror = (message, details) => {
    
    598
    -        lazy.logger.error(`Auto-Bootstrap error => ${message}; ${details}`);
    
    594
    +      bootstrap.onbootstraperror = error => {
    
    595
    +        lazy.logger.error("Auto-Bootstrap error", error);
    
    599 596
           };
    
    600 597
     
    
    601 598
           // Begin the bootstrap.
    
    ... ... @@ -620,14 +617,14 @@ class AutoBootstrappingState extends StateCallback {
    620 617
           }
    
    621 618
           if (success) {
    
    622 619
             // Persist the current settings to preferences.
    
    623
    -        TorSettings.setSettings(currentSetting);
    
    624
    -        TorSettings.saveToPrefs();
    
    620
    +        lazy.TorSettings.setSettings(currentSetting);
    
    621
    +        lazy.TorSettings.saveToPrefs();
    
    625 622
             // Do not await `applySettings`. Otherwise this opens up a window of
    
    626 623
             // time where the user can still "Cancel" the bootstrap.
    
    627 624
             // We are calling `applySettings` just to be on the safe side, but the
    
    628 625
             // settings we are passing now should be exactly the same we already
    
    629 626
             // passed earlier.
    
    630
    -        TorSettings.applySettings().catch(e =>
    
    627
    +        lazy.TorSettings.applySettings().catch(e =>
    
    631 628
               lazy.logger.error("TorSettings.applySettings threw unexpectedly.", e)
    
    632 629
             );
    
    633 630
             this.changeState(TorConnectState.Bootstrapped);
    
    ... ... @@ -638,19 +635,10 @@ class AutoBootstrappingState extends StateCallback {
    638 635
         // Only explicitly change state here if something else has not transitioned
    
    639 636
         // us.
    
    640 637
         if (!this.transitioning) {
    
    641
    -      this.#throwError(
    
    642
    -        TorStrings.torConnect.autoBootstrappingFailed,
    
    643
    -        TorStrings.torConnect.autoBootstrappingAllFailed
    
    644
    -      );
    
    638
    +      throw new TorConnectError(TorConnectError.AllSettingsFailed);
    
    645 639
         }
    
    646 640
       }
    
    647 641
     
    
    648
    -  #throwError(message, details) {
    
    649
    -    let err = new Error(message);
    
    650
    -    err.details = details;
    
    651
    -    throw err;
    
    652
    -  }
    
    653
    -
    
    654 642
       transitionRequested() {
    
    655 643
         this.#transitionResolve();
    
    656 644
       }
    
    ... ... @@ -662,7 +650,7 @@ class AutoBootstrappingState extends StateCallback {
    662 650
     
    
    663 651
         if (this.#changedSettings && nextState !== TorConnectState.Bootstrapped) {
    
    664 652
           try {
    
    665
    -        await TorSettings.applySettings();
    
    653
    +        await lazy.TorSettings.applySettings();
    
    666 654
           } catch (e) {
    
    667 655
             // We cannot do much if the original settings were bad or
    
    668 656
             // if the connection closed, so just report it in the
    
    ... ... @@ -698,17 +686,15 @@ class ErrorState extends StateCallback {
    698 686
         ErrorState.#hasEverHappened = true;
    
    699 687
       }
    
    700 688
     
    
    701
    -  run(errorMessage, errorDetails) {
    
    702
    -    TorConnect._errorMessage = errorMessage;
    
    703
    -    TorConnect._errorDetails = errorDetails;
    
    704
    -    lazy.logger.error(
    
    705
    -      `Entering error state (${errorMessage}, ${errorDetails})`
    
    706
    -    );
    
    689
    +  run(error) {
    
    690
    +    if (!(error instanceof TorConnectError)) {
    
    691
    +      error = new TorConnectError(TorConnectError.ExternalError, error);
    
    692
    +    }
    
    693
    +    TorConnect._errorCode = error.code;
    
    694
    +    TorConnect._errorDetails = error;
    
    695
    +    lazy.logger.error(`Entering error state (${error.code})`, error);
    
    707 696
     
    
    708
    -    Services.obs.notifyObservers(
    
    709
    -      { message: errorMessage, details: errorDetails },
    
    710
    -      TorConnectTopics.BootstrapError
    
    711
    -    );
    
    697
    +    Services.obs.notifyObservers(error, TorConnectTopics.Error);
    
    712 698
     
    
    713 699
         this.changeState(TorConnectState.Configuring);
    
    714 700
       }
    
    ... ... @@ -835,7 +821,6 @@ class InternetTest {
    835 821
     export const TorConnect = {
    
    836 822
       _stateHandler: new InitialState(),
    
    837 823
       _bootstrapProgress: 0,
    
    838
    -  _bootstrapStatus: null,
    
    839 824
       _internetStatus: InternetStatus.Unknown,
    
    840 825
       // list of country codes Moat has settings for
    
    841 826
       _countryCodes: [],
    
    ... ... @@ -851,7 +836,7 @@ export const TorConnect = {
    851 836
         })()
    
    852 837
       ),
    
    853 838
       _detectedLocation: "",
    
    854
    -  _errorMessage: null,
    
    839
    +  _errorCode: null,
    
    855 840
       _errorDetails: null,
    
    856 841
       _logHasWarningOrError: false,
    
    857 842
       _hasBootstrapEverFailed: false,
    
    ... ... @@ -925,17 +910,15 @@ export const TorConnect = {
    925 910
         this._stateHandler.begin(...args);
    
    926 911
       },
    
    927 912
     
    
    928
    -  _updateBootstrapStatus(progress, status) {
    
    913
    +  _updateBootstrapProgress(progress, status) {
    
    929 914
         this._bootstrapProgress = progress;
    
    930
    -    this._bootstrapStatus = status;
    
    931 915
     
    
    932 916
         lazy.logger.info(
    
    933
    -      `Bootstrapping ${this._bootstrapProgress}% complete (${this._bootstrapStatus})`
    
    917
    +      `Bootstrapping ${this._bootstrapProgress}% complete (${status})`
    
    934 918
         );
    
    935 919
         Services.obs.notifyObservers(
    
    936 920
           {
    
    937 921
             progress: TorConnect._bootstrapProgress,
    
    938
    -        status: TorConnect._bootstrapStatus,
    
    939 922
             hasWarnings: TorConnect._logHasWarningOrError,
    
    940 923
           },
    
    941 924
           TorConnectTopics.BootstrapProgress
    
    ... ... @@ -964,11 +947,13 @@ export const TorConnect = {
    964 947
           // So, we prefer initializing TorConnect as soon as possible, so that
    
    965 948
           // the UI will be able to detect it is in the Initializing state and act
    
    966 949
           // consequently.
    
    967
    -      TorSettings.initializedPromise.then(() => this._settingsInitialized());
    
    950
    +      lazy.TorSettings.initializedPromise.then(() =>
    
    951
    +        this._settingsInitialized()
    
    952
    +      );
    
    968 953
     
    
    969 954
           // register the Tor topics we always care about
    
    970
    -      observeTopic(TorTopics.ProcessExited);
    
    971
    -      observeTopic(TorTopics.LogHasWarnOrErr);
    
    955
    +      observeTopic(lazy.TorProviderTopics.ProcessExited);
    
    956
    +      observeTopic(lazy.TorProviderTopics.HasWarnOrErr);
    
    972 957
         }
    
    973 958
       },
    
    974 959
     
    
    ... ... @@ -976,11 +961,11 @@ export const TorConnect = {
    976 961
         lazy.logger.debug(`Observed ${topic}`);
    
    977 962
     
    
    978 963
         switch (topic) {
    
    979
    -      case TorTopics.LogHasWarnOrErr: {
    
    964
    +      case lazy.TorProviderTopics.HasWarnOrErr: {
    
    980 965
             this._logHasWarningOrError = true;
    
    981 966
             break;
    
    982 967
           }
    
    983
    -      case TorTopics.ProcessExited: {
    
    968
    +      case lazy.TorProviderTopics.ProcessExited: {
    
    984 969
             // Treat a failure as a possibly broken configuration.
    
    985 970
             // So, prevent quickstart at the next start.
    
    986 971
             Services.prefs.setBoolPref(TorLauncherPrefs.prompt_at_startup, true);
    
    ... ... @@ -1048,7 +1033,7 @@ export const TorConnect = {
    1048 1033
         // FIXME: This is called before the TorProvider is ready.
    
    1049 1034
         // As a matter of fact, at the moment it is equivalent to the following
    
    1050 1035
         // line, but this might become a problem in the future.
    
    1051
    -    return TorLauncherUtil.shouldStartAndOwnTor;
    
    1036
    +    return lazy.TorLauncherUtil.shouldStartAndOwnTor;
    
    1052 1037
       },
    
    1053 1038
     
    
    1054 1039
       get shouldShowTorConnect() {
    
    ... ... @@ -1089,7 +1074,7 @@ export const TorConnect = {
    1089 1074
       get shouldQuickStart() {
    
    1090 1075
         // quickstart must be enabled
    
    1091 1076
         return (
    
    1092
    -      TorSettings.quickstart.enabled &&
    
    1077
    +      lazy.TorSettings.quickstart.enabled &&
    
    1093 1078
           // and the previous bootstrap attempt must have succeeded
    
    1094 1079
           !Services.prefs.getBoolPref(TorLauncherPrefs.prompt_at_startup, true)
    
    1095 1080
         );
    
    ... ... @@ -1103,10 +1088,6 @@ export const TorConnect = {
    1103 1088
         return this._bootstrapProgress;
    
    1104 1089
       },
    
    1105 1090
     
    
    1106
    -  get bootstrapStatus() {
    
    1107
    -    return this._bootstrapStatus;
    
    1108
    -  },
    
    1109
    -
    
    1110 1091
       get internetStatus() {
    
    1111 1092
         return this._internetStatus;
    
    1112 1093
       },
    
    ... ... @@ -1123,8 +1104,8 @@ export const TorConnect = {
    1123 1104
         return this._detectedLocation;
    
    1124 1105
       },
    
    1125 1106
     
    
    1126
    -  get errorMessage() {
    
    1127
    -    return this._errorMessage;
    
    1107
    +  get errorCode() {
    
    1108
    +    return this._errorCode;
    
    1128 1109
       },
    
    1129 1110
     
    
    1130 1111
       get errorDetails() {
    
    ... ... @@ -1195,7 +1176,7 @@ export const TorConnect = {
    1195 1176
         Further external commands and helper methods
    
    1196 1177
        */
    
    1197 1178
       openTorPreferences() {
    
    1198
    -    if (TorLauncherUtil.isAndroid) {
    
    1179
    +    if (lazy.TorLauncherUtil.isAndroid) {
    
    1199 1180
           lazy.EventDispatcher.instance.sendRequest({
    
    1200 1181
             type: "GeckoView:Tor:OpenSettings",
    
    1201 1182
           });
    

  • toolkit/modules/TorStrings.sys.mjs
    ... ... @@ -51,11 +51,11 @@ class TorPropertyStringBundle {
    51 51
         return `$(${key})`;
    
    52 52
       }
    
    53 53
     
    
    54
    -  getStrings(strings) {
    
    54
    +  getStrings(strings, additionalPrefix = "") {
    
    55 55
         return Object.fromEntries(
    
    56 56
           Object.entries(strings).map(([key, fallback]) => [
    
    57 57
             key,
    
    58
    -        this.getString(key, fallback),
    
    58
    +        this.getString(additionalPrefix + key, fallback),
    
    59 59
           ])
    
    60 60
         );
    
    61 61
       }
    
    ... ... @@ -143,7 +143,7 @@ const Loader = {
    143 143
           frequentLocations: "Frequently selected locations",
    
    144 144
           otherLocations: "Other locations",
    
    145 145
     
    
    146
    -      // TorConnect.jsm error messages
    
    146
    +      // TorConnect error messages
    
    147 147
           offline: "Internet not reachable",
    
    148 148
           autoBootstrappingFailed: "Automatic configuration failed",
    
    149 149
           autoBootstrappingAllFailed: "None of the configurations we tried worked",
    
    ... ... @@ -158,11 +158,67 @@ const Loader = {
    158 158
           titlebarStatusConnected: "Connected",
    
    159 159
         };
    
    160 160
     
    
    161
    +    // Some strings were used through TorLauncherUtils.
    
    162
    +    // However, we need to use them in about:torconnect, which cannot access
    
    163
    +    // privileged code.
    
    164
    +    const bootstrapStatus = {
    
    165
    +      starting: "Starting",
    
    166
    +      conn_pt: "Connecting to bridge",
    
    167
    +      conn_done_pt: "Connected to bridge",
    
    168
    +      conn_proxy: "Connecting to proxy",
    
    169
    +      conn_done_proxy: "Connected to proxy",
    
    170
    +      conn: "Connecting to a Tor relay",
    
    171
    +      conn_done: "Connected to a Tor relay",
    
    172
    +      handshake: "Negotiating with a Tor relay",
    
    173
    +      handshake_done: "Finished negotiating with a Tor relay",
    
    174
    +      onehop_create: "Establishing an encrypted directory connection",
    
    175
    +      requesting_status: "Retrieving network status",
    
    176
    +      loading_status: "Loading network status",
    
    177
    +      loading_keys: "Loading authority certificates",
    
    178
    +      requesting_descriptors: "Requesting relay information",
    
    179
    +      loading_descriptors: "Loading relay information",
    
    180
    +      enough_dirinfo: "Finished loading relay information",
    
    181
    +      ap_conn_pt: "Building circuits: Connecting to bridge",
    
    182
    +      ap_conn_done_pt: "Building circuits: Connected to bridge",
    
    183
    +      ap_conn_proxy: "Building circuits: Connecting to proxy",
    
    184
    +      ap_conn_done_proxy: "Building circuits: Connected to proxy",
    
    185
    +      ap_conn: "Building circuits: Connecting to a Tor relay",
    
    186
    +      ap_conn_done: "Building circuits: Connected to a Tor relay",
    
    187
    +      ap_handshake: "Building circuits: Negotiating with a Tor relay",
    
    188
    +      ap_handshake_done:
    
    189
    +        "Building circuits: Finished negotiating with a Tor relay",
    
    190
    +      circuit_create: "Building circuits: Establishing a Tor circuit",
    
    191
    +      done: "Connected to the Tor network!",
    
    192
    +    };
    
    193
    +    const bootstrapWarning = {
    
    194
    +      done: "done",
    
    195
    +      connectrefused: "connection refused",
    
    196
    +      misc: "miscellaneous",
    
    197
    +      resourcelimit: "insufficient resources",
    
    198
    +      identity: "identity mismatch",
    
    199
    +      timeout: "connection timeout",
    
    200
    +      noroute: "no route to host",
    
    201
    +      ioerror: "read/write error",
    
    202
    +      pt_missing: "missing pluggable transport",
    
    203
    +    };
    
    204
    +
    
    161 205
         const tsb = new TorPropertyStringBundle(
    
    162 206
           "chrome://torbutton/locale/torConnect.properties",
    
    163 207
           "torConnect."
    
    164 208
         );
    
    165
    -    return tsb.getStrings(strings);
    
    209
    +    const tlsb = new TorPropertyStringBundle(
    
    210
    +      "chrome://torbutton/locale/torlauncher.properties",
    
    211
    +      "torlauncher."
    
    212
    +    );
    
    213
    +    return {
    
    214
    +      ...tsb.getStrings(strings),
    
    215
    +      bootstrapFailedDetails: tlsb.getString(
    
    216
    +        "tor_bootstrap_failed_details",
    
    217
    +        "%1$S failed (%2$S)."
    
    218
    +      ),
    
    219
    +      bootstrapStatus: tlsb.getStrings(bootstrapStatus, "bootstrapStatus."),
    
    220
    +      bootstrapWarning: tlsb.getStrings(bootstrapWarning, "bootstrapWarning."),
    
    221
    +    };
    
    166 222
       },
    
    167 223
     
    
    168 224
       /*
    

  • toolkit/torbutton/chrome/locale/en-US/torlauncher.properties
    ... ... @@ -4,20 +4,15 @@
    4 4
     # file, You can obtain one at http://mozilla.org/MPL/2.0/.
    
    5 5
     
    
    6 6
     torlauncher.error_title=Tor Launcher
    
    7
    -
    
    8 7
     torlauncher.tor_exited_during_startup=Tor exited during startup. This might be due to an error in your torrc file, a bug in Tor or another program on your system, or faulty hardware. Until you fix the underlying problem and restart Tor, Tor Browser will not start.
    
    9 8
     torlauncher.tor_exited=Tor unexpectedly exited. This might be due to a bug in Tor itself, another program on your system, or faulty hardware. Until you restart Tor, Tor Browser will not be able to reach any websites. If the problem persists, please send a copy of your Tor Log to the support team.
    
    10 9
     torlauncher.tor_exited2=Restarting Tor will not close your browser tabs.
    
    11 10
     torlauncher.restart_tor=Restart Tor
    
    12
    -torlauncher.tor_bootstrap_failed=Tor failed to establish a Tor network connection.
    
    13
    -torlauncher.tor_bootstrap_failed_details=%1$S failed (%2$S).
    
    14 11
     
    
    15
    -torlauncher.unable_to_start_tor=Unable to start Tor.\n\n%S
    
    16
    -torlauncher.tor_missing=The Tor executable is missing.
    
    17
    -torlauncher.torrc_missing=The torrc file is missing and could not be created.
    
    18
    -torlauncher.datadir_missing=The Tor data directory does not exist and could not be created.
    
    19
    -torlauncher.onionauthdir_missing=The Tor onion authentication directory does not exist and could not be created.
    
    20
    -torlauncher.password_hash_missing=Failed to get hashed password.
    
    12
    +
    
    13
    +# Translation note: %1$S is a bootstrap phase from torlauncher.bootstrapStatus,
    
    14
    +# %2$S is the error from torlauncher.bootstrapWarning
    
    15
    +torlauncher.tor_bootstrap_failed_details=%1$S failed (%2$S).
    
    21 16
     
    
    22 17
     torlauncher.bootstrapStatus.starting=Starting
    
    23 18
     torlauncher.bootstrapStatus.conn_pt=Connecting to bridge
    

  • _______________________________________________
    tor-commits mailing list
    tor-commits@xxxxxxxxxxxxxxxxxxxx
    https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits