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

Commits:

7 changed files:

Changes:

  • browser/components/rulesets/RulesetsParent.sys.mjs
    1 1
     // Copyright (c) 2022, The Tor Project, Inc.
    
    2 2
     
    
    3
    -import { TorStrings } from "resource://gre/modules/TorStrings.sys.mjs";
    
    4 3
     import {
    
    5 4
       OnionAliasStore,
    
    6 5
       OnionAliasStoreTopics,
    
    ... ... @@ -8,8 +7,8 @@ import {
    8 7
     
    
    9 8
     const kShowWarningPref = "torbrowser.rulesets.show_warning";
    
    10 9
     
    
    11
    -// This class allows about:rulesets to get TorStrings and to load/save the
    
    12
    -// preference for skipping the warning
    
    10
    +// This class allows about:rulesets to load/save the preference for skipping the
    
    11
    +// warning
    
    13 12
     export class RulesetsParent extends JSWindowActorParent {
    
    14 13
       constructor(...args) {
    
    15 14
         super(...args);
    
    ... ... @@ -53,7 +52,6 @@ export class RulesetsParent extends JSWindowActorParent {
    53 52
             return OnionAliasStore.getChannels();
    
    54 53
           case "rulesets:get-init-args":
    
    55 54
             return {
    
    56
    -          TorStrings,
    
    57 55
               showWarning: Services.prefs.getBoolPref(kShowWarningPref, true),
    
    58 56
             };
    
    59 57
           case "rulesets:set-channel":
    

  • browser/components/rulesets/content/aboutRulesets.html
    ... ... @@ -11,13 +11,19 @@
    11 11
           rel="stylesheet"
    
    12 12
           href="chrome://browser/content/rulesets/aboutRulesets.css"
    
    13 13
         />
    
    14
    +
    
    15
    +    <link rel="localization" href="branding/brand.ftl" />
    
    16
    +    <link rel="localization" href="browser/tor-browser.ftl" />
    
    14 17
       </head>
    
    15 18
       <body>
    
    16 19
         <!-- Warning -->
    
    17 20
         <div id="warning-wrapper">
    
    18 21
           <div id="warning">
    
    19
    -        <h1 id="warning-title"></h1>
    
    20
    -        <p id="warning-description"></p>
    
    22
    +        <h1 id="warning-title" data-l10n-id="rulesets-warning-heading"></h1>
    
    23
    +        <p
    
    24
    +          id="warning-description"
    
    25
    +          data-l10n-id="rulesets-warning-description"
    
    26
    +        ></p>
    
    21 27
             <p>
    
    22 28
               <label>
    
    23 29
                 <input
    
    ... ... @@ -25,11 +31,18 @@
    25 31
                   type="checkbox"
    
    26 32
                   checked="checked"
    
    27 33
                 />
    
    28
    -            <span id="warning-enable-label"></span>
    
    34
    +            <span
    
    35
    +              id="warning-enable-label"
    
    36
    +              data-l10n-id="rulesets-warning-checkbox"
    
    37
    +            ></span>
    
    29 38
               </label>
    
    30 39
             </p>
    
    31 40
             <div id="warning-buttonbar">
    
    32
    -          <button id="warning-button" autofocus="autofocus"></button>
    
    41
    +          <button
    
    42
    +            id="warning-button"
    
    43
    +            autofocus="autofocus"
    
    44
    +            data-l10n-id="rulesets-warning-continue-button"
    
    45
    +          ></button>
    
    33 46
             </div>
    
    34 47
           </div>
    
    35 48
         </div>
    
    ... ... @@ -37,11 +50,20 @@
    37 50
         <div id="main-content">
    
    38 51
           <!-- Ruleset list -->
    
    39 52
           <aside>
    
    40
    -        <div id="ruleset-heading"></div>
    
    53
    +        <div
    
    54
    +          id="ruleset-heading"
    
    55
    +          data-l10n-id="rulesets-side-panel-heading"
    
    56
    +        ></div>
    
    41 57
             <div id="ruleset-list-container">
    
    42 58
               <div id="ruleset-list-empty">
    
    43
    -            <p id="ruleset-list-empty-title"></p>
    
    44
    -            <p id="ruleset-list-empty-description"></p>
    
    59
    +            <p
    
    60
    +              id="ruleset-list-empty-title"
    
    61
    +              data-l10n-id="rulesets-side-panel-no-rules"
    
    62
    +            ></p>
    
    63
    +            <p
    
    64
    +              id="ruleset-list-empty-description"
    
    65
    +              data-l10n-id="rulesets-side-panel-no-rules-description"
    
    66
    +            ></p>
    
    45 67
               </div>
    
    46 68
               <ul id="ruleset-list">
    
    47 69
                 <li id="ruleset-template">
    
    ... ... @@ -59,24 +81,40 @@
    59 81
           <section id="ruleset-details">
    
    60 82
             <div class="title">
    
    61 83
               <h1 id="ruleset-title"></h1>
    
    62
    -          <button id="ruleset-edit" class="ghost-button"></button>
    
    84
    +          <button
    
    85
    +            id="ruleset-edit"
    
    86
    +            class="ghost-button"
    
    87
    +            data-l10n-id="rulesets-details-edit-button"
    
    88
    +          ></button>
    
    63 89
             </div>
    
    64 90
             <dl>
    
    65
    -          <dt id="ruleset-jwk-label"></dt>
    
    91
    +          <dt id="ruleset-jwk-label" data-l10n-id="rulesets-details-jwk"></dt>
    
    66 92
               <dd id="ruleset-jwk-value"></dd>
    
    67
    -          <dt id="ruleset-path-prefix-label"></dt>
    
    93
    +          <dt
    
    94
    +            id="ruleset-path-prefix-label"
    
    95
    +            data-l10n-id="rulesets-details-path"
    
    96
    +          ></dt>
    
    68 97
               <dd>
    
    69 98
                 <a id="ruleset-path-prefix-value" target="_blank"></a>
    
    70 99
               </dd>
    
    71
    -          <dt id="ruleset-scope-label"></dt>
    
    100
    +          <dt
    
    101
    +            id="ruleset-scope-label"
    
    102
    +            data-l10n-id="rulesets-details-scope"
    
    103
    +          ></dt>
    
    72 104
               <dd id="ruleset-scope-value"></dd>
    
    73 105
             </dl>
    
    74 106
             <label id="ruleset-enable">
    
    75 107
               <input type="checkbox" id="ruleset-enable-checkbox" />
    
    76
    -          <span id="ruleset-enable-label"></span>
    
    108
    +          <span
    
    109
    +            id="ruleset-enable-label"
    
    110
    +            data-l10n-id="rulesets-details-enable-checkbox"
    
    111
    +          ></span>
    
    77 112
             </label>
    
    78 113
             <div id="ruleset-buttonbar">
    
    79
    -          <button id="ruleset-update-button"></button>
    
    114
    +          <button
    
    115
    +            id="ruleset-update-button"
    
    116
    +            data-l10n-id="rulesets-details-update-button"
    
    117
    +          ></button>
    
    80 118
             </div>
    
    81 119
             <hr />
    
    82 120
             <p id="ruleset-updated"></p>
    
    ... ... @@ -89,24 +127,52 @@
    89 127
             </div>
    
    90 128
             <form id="edit-ruleset-form">
    
    91 129
               <label>
    
    92
    -            <div id="edit-jwk-label"></div>
    
    93
    -            <textarea id="edit-jwk-textarea" rows="10"></textarea>
    
    130
    +            <div id="edit-jwk-label" data-l10n-id="rulesets-details-jwk"></div>
    
    131
    +            <textarea
    
    132
    +              id="edit-jwk-textarea"
    
    133
    +              rows="10"
    
    134
    +              data-l10n-id="rulesets-details-jwk-input"
    
    135
    +            ></textarea>
    
    94 136
               </label>
    
    95 137
               <label>
    
    96
    -            <div id="edit-path-prefix-label"></div>
    
    97
    -            <input id="edit-path-prefix-input" type="text" />
    
    138
    +            <div
    
    139
    +              id="edit-path-prefix-label"
    
    140
    +              data-l10n-id="rulesets-details-path"
    
    141
    +            ></div>
    
    142
    +            <input
    
    143
    +              id="edit-path-prefix-input"
    
    144
    +              type="text"
    
    145
    +              data-l10n-id="rulesets-details-path-input"
    
    146
    +            />
    
    98 147
               </label>
    
    99 148
               <label>
    
    100
    -            <div id="edit-scope-label"></div>
    
    101
    -            <input id="edit-scope-input" type="text" />
    
    149
    +            <div
    
    150
    +              id="edit-scope-label"
    
    151
    +              data-l10n-id="rulesets-details-scope"
    
    152
    +            ></div>
    
    153
    +            <input
    
    154
    +              id="edit-scope-input"
    
    155
    +              type="text"
    
    156
    +              data-l10n-id="rulesets-details-scope-input"
    
    157
    +            />
    
    102 158
               </label>
    
    103 159
               <label id="edit-enable">
    
    104 160
                 <input type="checkbox" id="edit-enable-checkbox" />
    
    105
    -            <span id="edit-enable-label"></span>
    
    161
    +            <span
    
    162
    +              id="edit-enable-label"
    
    163
    +              data-l10n-id="rulesets-details-enable-checkbox"
    
    164
    +            ></span>
    
    106 165
               </label>
    
    107 166
               <div id="edit-buttonbar">
    
    108
    -            <button id="edit-save" class="primary"></button>
    
    109
    -            <button id="edit-cancel"></button>
    
    167
    +            <button
    
    168
    +              id="edit-save"
    
    169
    +              class="primary"
    
    170
    +              data-l10n-id="rulesets-details-save-button"
    
    171
    +            ></button>
    
    172
    +            <button
    
    173
    +              id="edit-cancel"
    
    174
    +              data-l10n-id="rulesets-details-cancel-button"
    
    175
    +            ></button>
    
    110 176
               </div>
    
    111 177
             </form>
    
    112 178
           </section>
    

  • browser/components/rulesets/content/aboutRulesets.js
    ... ... @@ -2,8 +2,6 @@
    2 2
     
    
    3 3
     /* globals RPMAddMessageListener, RPMSendQuery, RPMSendAsyncMessage */
    
    4 4
     
    
    5
    -let TorStrings;
    
    6
    -
    
    7 5
     const Orders = Object.freeze({
    
    8 6
       Name: "name",
    
    9 7
       NameDesc: "name-desc",
    
    ... ... @@ -19,55 +17,35 @@ const States = Object.freeze({
    19 17
     
    
    20 18
     function setUpdateDate(ruleset, element) {
    
    21 19
       if (!ruleset.enabled) {
    
    22
    -    element.textContent = TorStrings.rulesets.disabled;
    
    20
    +    document.l10n.setAttributes(element, "rulesets-update-rule-disabled");
    
    23 21
         return;
    
    24 22
       }
    
    25 23
       if (!ruleset.currentTimestamp) {
    
    26
    -    element.textContent = TorStrings.rulesets.neverUpdated;
    
    24
    +    document.l10n.setAttributes(element, "rulesets-update-never");
    
    27 25
         return;
    
    28 26
       }
    
    29 27
     
    
    30
    -  const formatter = new Intl.DateTimeFormat(navigator.languages, {
    
    31
    -    year: "numeric",
    
    32
    -    month: "long",
    
    33
    -    day: "numeric",
    
    28
    +  document.l10n.setAttributes(element, "rulesets-update-last", {
    
    29
    +    date: ruleset.currentTimestamp * 1000,
    
    34 30
       });
    
    35
    -  element.textContent = TorStrings.rulesets.lastUpdated.replace(
    
    36
    -    "%S",
    
    37
    -    formatter.format(new Date(ruleset.currentTimestamp * 1000))
    
    38
    -  );
    
    39 31
     }
    
    40 32
     
    
    41 33
     class WarningState {
    
    42
    -  selectors = Object.freeze({
    
    43
    -    wrapper: "#warning-wrapper",
    
    44
    -    title: "#warning-title",
    
    45
    -    description: "#warning-description",
    
    46
    -    enableCheckbox: "#warning-enable-checkbox",
    
    47
    -    enableLabel: "#warning-enable-label",
    
    48
    -    button: "#warning-button",
    
    49
    -  });
    
    50
    -
    
    51
    -  elements = Object.freeze({
    
    52
    -    wrapper: document.querySelector(this.selectors.wrapper),
    
    53
    -    title: document.querySelector(this.selectors.title),
    
    54
    -    description: document.querySelector(this.selectors.description),
    
    55
    -    enableCheckbox: document.querySelector(this.selectors.enableCheckbox),
    
    56
    -    enableLabel: document.querySelector(this.selectors.enableLabel),
    
    57
    -    button: document.querySelector(this.selectors.button),
    
    58
    -  });
    
    34
    +  elements = {
    
    35
    +    enableCheckbox: document.getElementById("warning-enable-checkbox"),
    
    36
    +    button: document.getElementById("warning-button"),
    
    37
    +  };
    
    59 38
     
    
    60 39
       constructor() {
    
    61
    -    const elements = this.elements;
    
    62
    -    elements.title.textContent = TorStrings.rulesets.warningTitle;
    
    63
    -    elements.description.textContent = TorStrings.rulesets.warningDescription;
    
    64
    -    elements.enableLabel.textContent = TorStrings.rulesets.warningEnable;
    
    65
    -    elements.button.textContent = TorStrings.rulesets.warningButton;
    
    66
    -    elements.enableCheckbox.addEventListener(
    
    40
    +    this.elements.enableCheckbox.addEventListener(
    
    67 41
           "change",
    
    68 42
           this.onEnableChange.bind(this)
    
    69 43
         );
    
    70
    -    elements.button.addEventListener("click", this.onButtonClick.bind(this));
    
    44
    +
    
    45
    +    this.elements.button.addEventListener(
    
    46
    +      "click",
    
    47
    +      this.onButtonClick.bind(this)
    
    48
    +    );
    
    71 49
       }
    
    72 50
     
    
    73 51
       show() {
    
    ... ... @@ -89,50 +67,28 @@ class WarningState {
    89 67
     }
    
    90 68
     
    
    91 69
     class DetailsState {
    
    92
    -  selectors = Object.freeze({
    
    93
    -    title: "#ruleset-title",
    
    94
    -    edit: "#ruleset-edit",
    
    95
    -    jwkLabel: "#ruleset-jwk-label",
    
    96
    -    jwkValue: "#ruleset-jwk-value",
    
    97
    -    pathPrefixLabel: "#ruleset-path-prefix-label",
    
    98
    -    pathPrefixValue: "#ruleset-path-prefix-value",
    
    99
    -    scopeLabel: "#ruleset-scope-label",
    
    100
    -    scopeValue: "#ruleset-scope-value",
    
    101
    -    enableCheckbox: "#ruleset-enable-checkbox",
    
    102
    -    enableLabel: "#ruleset-enable-label",
    
    103
    -    updateButton: "#ruleset-update-button",
    
    104
    -    updated: "#ruleset-updated",
    
    105
    -  });
    
    106
    -
    
    107
    -  elements = Object.freeze({
    
    108
    -    title: document.querySelector(this.selectors.title),
    
    109
    -    edit: document.querySelector(this.selectors.edit),
    
    110
    -    jwkLabel: document.querySelector(this.selectors.jwkLabel),
    
    111
    -    jwkValue: document.querySelector(this.selectors.jwkValue),
    
    112
    -    pathPrefixLabel: document.querySelector(this.selectors.pathPrefixLabel),
    
    113
    -    pathPrefixValue: document.querySelector(this.selectors.pathPrefixValue),
    
    114
    -    scopeLabel: document.querySelector(this.selectors.scopeLabel),
    
    115
    -    scopeValue: document.querySelector(this.selectors.scopeValue),
    
    116
    -    enableCheckbox: document.querySelector(this.selectors.enableCheckbox),
    
    117
    -    enableLabel: document.querySelector(this.selectors.enableLabel),
    
    118
    -    updateButton: document.querySelector(this.selectors.updateButton),
    
    119
    -    updated: document.querySelector(this.selectors.updated),
    
    120
    -  });
    
    70
    +  elements = {
    
    71
    +    title: document.getElementById("ruleset-title"),
    
    72
    +    jwkValue: document.getElementById("ruleset-jwk-value"),
    
    73
    +    pathPrefixValue: document.getElementById("ruleset-path-prefix-value"),
    
    74
    +    scopeValue: document.getElementById("ruleset-scope-value"),
    
    75
    +    enableCheckbox: document.getElementById("ruleset-enable-checkbox"),
    
    76
    +    updateButton: document.getElementById("ruleset-update-button"),
    
    77
    +    updated: document.getElementById("ruleset-updated"),
    
    78
    +  };
    
    121 79
     
    
    122 80
       constructor() {
    
    123
    -    const elements = this.elements;
    
    124
    -    elements.edit.textContent = TorStrings.rulesets.edit;
    
    125
    -    elements.edit.addEventListener("click", this.onEdit.bind(this));
    
    126
    -    elements.jwkLabel.textContent = TorStrings.rulesets.jwk;
    
    127
    -    elements.pathPrefixLabel.textContent = TorStrings.rulesets.pathPrefix;
    
    128
    -    elements.scopeLabel.textContent = TorStrings.rulesets.scope;
    
    129
    -    elements.enableCheckbox.addEventListener(
    
    81
    +    document
    
    82
    +      .getElementById("ruleset-edit")
    
    83
    +      .addEventListener("click", this.onEdit.bind(this));
    
    84
    +    this.elements.enableCheckbox.addEventListener(
    
    130 85
           "change",
    
    131 86
           this.onEnable.bind(this)
    
    132 87
         );
    
    133
    -    elements.enableLabel.textContent = TorStrings.rulesets.enable;
    
    134
    -    elements.updateButton.textContent = TorStrings.rulesets.checkUpdates;
    
    135
    -    elements.updateButton.addEventListener("click", this.onUpdate.bind(this));
    
    88
    +    this.elements.updateButton.addEventListener(
    
    89
    +      "click",
    
    90
    +      this.onUpdate.bind(this)
    
    91
    +    );
    
    136 92
       }
    
    137 93
     
    
    138 94
       show(ruleset) {
    
    ... ... @@ -179,61 +135,22 @@ class DetailsState {
    179 135
     }
    
    180 136
     
    
    181 137
     class EditState {
    
    182
    -  selectors = Object.freeze({
    
    183
    -    form: "#edit-ruleset-form",
    
    184
    -    title: "#edit-title",
    
    185
    -    nameGroup: "#edit-name-group",
    
    186
    -    nameLabel: "#edit-name-label",
    
    187
    -    nameInput: "#edit-name-input",
    
    188
    -    jwkLabel: "#edit-jwk-label",
    
    189
    -    jwkTextarea: "#edit-jwk-textarea",
    
    190
    -    pathPrefixLabel: "#edit-path-prefix-label",
    
    191
    -    pathPrefixInput: "#edit-path-prefix-input",
    
    192
    -    scopeLabel: "#edit-scope-label",
    
    193
    -    scopeInput: "#edit-scope-input",
    
    194
    -    enableCheckbox: "#edit-enable-checkbox",
    
    195
    -    enableLabel: "#edit-enable-label",
    
    196
    -    save: "#edit-save",
    
    197
    -    cancel: "#edit-cancel",
    
    198
    -  });
    
    199
    -
    
    200
    -  elements = Object.freeze({
    
    201
    -    form: document.querySelector(this.selectors.form),
    
    202
    -    title: document.querySelector(this.selectors.title),
    
    203
    -    jwkLabel: document.querySelector(this.selectors.jwkLabel),
    
    204
    -    jwkTextarea: document.querySelector(this.selectors.jwkTextarea),
    
    205
    -    pathPrefixLabel: document.querySelector(this.selectors.pathPrefixLabel),
    
    206
    -    pathPrefixInput: document.querySelector(this.selectors.pathPrefixInput),
    
    207
    -    scopeLabel: document.querySelector(this.selectors.scopeLabel),
    
    208
    -    scopeInput: document.querySelector(this.selectors.scopeInput),
    
    209
    -    enableCheckbox: document.querySelector(this.selectors.enableCheckbox),
    
    210
    -    enableLabel: document.querySelector(this.selectors.enableLabel),
    
    211
    -    save: document.querySelector(this.selectors.save),
    
    212
    -    cancel: document.querySelector(this.selectors.cancel),
    
    213
    -  });
    
    138
    +  elements = {
    
    139
    +    form: document.getElementById("edit-ruleset-form"),
    
    140
    +    title: document.getElementById("edit-title"),
    
    141
    +    jwkTextarea: document.getElementById("edit-jwk-textarea"),
    
    142
    +    pathPrefixInput: document.getElementById("edit-path-prefix-input"),
    
    143
    +    scopeInput: document.getElementById("edit-scope-input"),
    
    144
    +    enableCheckbox: document.getElementById("edit-enable-checkbox"),
    
    145
    +  };
    
    214 146
     
    
    215 147
       constructor() {
    
    216
    -    const elements = this.elements;
    
    217
    -    elements.jwkLabel.textContent = TorStrings.rulesets.jwk;
    
    218
    -    elements.jwkTextarea.setAttribute(
    
    219
    -      "placeholder",
    
    220
    -      TorStrings.rulesets.jwkPlaceholder
    
    221
    -    );
    
    222
    -    elements.pathPrefixLabel.textContent = TorStrings.rulesets.pathPrefix;
    
    223
    -    elements.pathPrefixInput.setAttribute(
    
    224
    -      "placeholder",
    
    225
    -      TorStrings.rulesets.pathPrefixPlaceholder
    
    226
    -    );
    
    227
    -    elements.scopeLabel.textContent = TorStrings.rulesets.scope;
    
    228
    -    elements.scopeInput.setAttribute(
    
    229
    -      "placeholder",
    
    230
    -      TorStrings.rulesets.scopePlaceholder
    
    231
    -    );
    
    232
    -    elements.enableLabel.textContent = TorStrings.rulesets.enable;
    
    233
    -    elements.save.textContent = TorStrings.rulesets.save;
    
    234
    -    elements.save.addEventListener("click", this.onSave.bind(this));
    
    235
    -    elements.cancel.textContent = TorStrings.rulesets.cancel;
    
    236
    -    elements.cancel.addEventListener("click", this.onCancel.bind(this));
    
    148
    +    document
    
    149
    +      .getElementById("edit-save")
    
    150
    +      .addEventListener("click", this.onSave.bind(this));
    
    151
    +    document
    
    152
    +      .getElementById("edit-cancel")
    
    153
    +      .addEventListener("click", this.onCancel.bind(this));
    
    237 154
       }
    
    238 155
     
    
    239 156
       show(ruleset) {
    
    ... ... @@ -276,7 +193,9 @@ class EditState {
    276 193
           elements.jwkTextarea.setCustomValidity("");
    
    277 194
         } catch (err) {
    
    278 195
           console.error("Invalid JSON or invalid JWK", err);
    
    279
    -      elements.jwkTextarea.setCustomValidity(TorStrings.rulesets.jwkInvalid);
    
    196
    +      elements.jwkTextarea.setCustomValidity(
    
    197
    +        await document.l10n.formatValue("rulesets-details-jwk-input-invalid")
    
    198
    +      );
    
    280 199
           valid = false;
    
    281 200
         }
    
    282 201
     
    
    ... ... @@ -285,7 +204,7 @@ class EditState {
    285 204
           const url = new URL(pathPrefix);
    
    286 205
           if (url.protocol !== "http:" && url.protocol !== "https:") {
    
    287 206
             elements.pathPrefixInput.setCustomValidity(
    
    288
    -          TorStrings.rulesets.pathPrefixInvalid
    
    207
    +          await document.l10n.formatValue("rulesets-details-path-input-invalid")
    
    289 208
             );
    
    290 209
             valid = false;
    
    291 210
           } else {
    
    ... ... @@ -294,7 +213,7 @@ class EditState {
    294 213
         } catch (err) {
    
    295 214
           console.error("The path prefix is not a valid URL", err);
    
    296 215
           elements.pathPrefixInput.setCustomValidity(
    
    297
    -        TorStrings.rulesets.pathPrefixInvalid
    
    216
    +        await document.l10n.formatValue("rulesets-details-path-input-invalid")
    
    298 217
           );
    
    299 218
           valid = false;
    
    300 219
         }
    
    ... ... @@ -304,7 +223,9 @@ class EditState {
    304 223
           scope = new RegExp(elements.scopeInput.value.trim());
    
    305 224
           elements.scopeInput.setCustomValidity("");
    
    306 225
         } catch (err) {
    
    307
    -      elements.scopeInput.setCustomValidity(TorStrings.rulesets.scopeInvalid);
    
    226
    +      elements.scopeInput.setCustomValidity(
    
    227
    +        await document.l10n.formatValue("rulesets-details-scope-input-invalid")
    
    228
    +      );
    
    308 229
           valid = false;
    
    309 230
         }
    
    310 231
     
    
    ... ... @@ -342,39 +263,17 @@ class NoRulesetsState {
    342 263
     }
    
    343 264
     
    
    344 265
     class RulesetList {
    
    345
    -  selectors = Object.freeze({
    
    346
    -    heading: "#ruleset-heading",
    
    347
    -    list: "#ruleset-list",
    
    348
    -    emptyContainer: "#ruleset-list-empty",
    
    349
    -    emptyTitle: "#ruleset-list-empty-title",
    
    350
    -    emptyDescription: "#ruleset-list-empty-description",
    
    351
    -    itemTemplate: "#ruleset-template",
    
    352
    -    itemName: ".name",
    
    353
    -    itemDescr: ".description",
    
    354
    -  });
    
    355
    -
    
    356
    -  elements = Object.freeze({
    
    357
    -    heading: document.querySelector(this.selectors.heading),
    
    358
    -    list: document.querySelector(this.selectors.list),
    
    359
    -    emptyContainer: document.querySelector(this.selectors.emptyContainer),
    
    360
    -    emptyTitle: document.querySelector(this.selectors.emptyTitle),
    
    361
    -    emptyDescription: document.querySelector(this.selectors.emptyDescription),
    
    362
    -    itemTemplate: document.querySelector(this.selectors.itemTemplate),
    
    363
    -  });
    
    266
    +  elements = {
    
    267
    +    list: document.getElementById("ruleset-list"),
    
    268
    +    emptyContainer: document.getElementById("ruleset-list-empty"),
    
    269
    +    itemTemplate: document.getElementById("ruleset-template"),
    
    270
    +  };
    
    364 271
     
    
    365 272
       nameAttribute = "data-name";
    
    366 273
     
    
    367 274
       rulesets = [];
    
    368 275
     
    
    369 276
       constructor() {
    
    370
    -    const elements = this.elements;
    
    371
    -
    
    372
    -    // Header
    
    373
    -    elements.heading.textContent = TorStrings.rulesets.rulesets;
    
    374
    -    // Empty
    
    375
    -    elements.emptyTitle.textContent = TorStrings.rulesets.noRulesets;
    
    376
    -    elements.emptyDescription.textContent = TorStrings.rulesets.noRulesetsDescr;
    
    377
    -
    
    378 277
         RPMAddMessageListener(
    
    379 278
           "rulesets:channels-change",
    
    380 279
           this.onRulesetsChanged.bind(this)
    
    ... ... @@ -438,14 +337,10 @@ class RulesetList {
    438 337
         const item = this.elements.itemTemplate.cloneNode(true);
    
    439 338
         item.removeAttribute("id");
    
    440 339
         item.classList.add("item");
    
    441
    -    item.querySelector(this.selectors.itemName).textContent = ruleset.name;
    
    442
    -    const descr = item.querySelector(this.selectors.itemDescr);
    
    443
    -    if (ruleset.enabled) {
    
    444
    -      setUpdateDate(ruleset, descr);
    
    445
    -    } else {
    
    446
    -      descr.textContent = TorStrings.rulesets.disabled;
    
    447
    -      item.classList.add("disabled");
    
    448
    -    }
    
    340
    +    item.querySelector(".name").textContent = ruleset.name;
    
    341
    +    const descr = item.querySelector(".description");
    
    342
    +    setUpdateDate(ruleset, descr);
    
    343
    +    item.classList.toggle("disabled", !ruleset.enabled);
    
    449 344
         item.setAttribute(this.nameAttribute, ruleset.name);
    
    450 345
         item.addEventListener("click", () => {
    
    451 346
           this.onRulesetClick(ruleset);
    
    ... ... @@ -478,7 +373,6 @@ class AboutRulesets {
    478 373
     
    
    479 374
       async init() {
    
    480 375
         const args = await RPMSendQuery("rulesets:get-init-args");
    
    481
    -    TorStrings = args.TorStrings;
    
    482 376
         const showWarning = args.showWarning;
    
    483 377
     
    
    484 378
         this.list = new RulesetList();
    

  • browser/locales/en-US/browser/tor-browser.ftl
    ... ... @@ -557,3 +557,53 @@ downloads-tor-warning-title = Be careful opening downloads
    557 557
     downloads-tor-warning-description = Some files may connect to the internet when opened without using Tor. To be safe, open the files while offline or use a portable operating system like <a data-l10n-name="tails-link">Tails</a>.
    
    558 558
     # Button to dismiss the warning forever.
    
    559 559
     downloads-tor-warning-dismiss-button = Got it
    
    560
    +
    
    561
    +## Initial warning page in about:rulesets. In Tor Browser, each ruleset is a set of rules for converting a ".tor.onion" address to a normal ".onion" address (used by SecureDrop). The feature is taken from the discontinued "HTTPS Everywhere".
    
    562
    +
    
    563
    +rulesets-warning-heading = Proceed with Caution
    
    564
    +rulesets-warning-description = Adding or modifying rulesets can cause attackers to hijack your browser. Proceed only if you know what you are doing.
    
    565
    +rulesets-warning-checkbox = Warn me when I attempt to access these preferences
    
    566
    +rulesets-warning-continue-button = Accept the Risk and Continue
    
    567
    +
    
    568
    +## Side panel in about:rulesets. In Tor Browser, each ruleset is a set of rules for converting a ".tor.onion" address to a normal ".onion" address (used by SecureDrop). The feature is taken from the discontinued "HTTPS Everywhere".
    
    569
    +
    
    570
    +rulesets-side-panel-heading = Rulesets
    
    571
    +rulesets-side-panel-no-rules = No rulesets found
    
    572
    +# -brand-short-name refers to 'Tor Browser', localized.
    
    573
    +rulesets-side-panel-no-rules-description = When you save a ruleset in { -brand-short-name }, it will show up here.
    
    574
    +
    
    575
    +## Ruleset update date in about:rulesets.
    
    576
    +
    
    577
    +# $date (Date) - The update date. The DATETIME function will format the $date according to the locale, using a "long" style. E.g. "January 1, 2000" for English (US), "١ يناير ٢٠٠٠" for Arabic, "2000년 1월 1일" in Korean, and "1 января 2000 г." in Russian.
    
    578
    +rulesets-update-last = Last updated { DATETIME($date, dateStyle: "long") }
    
    579
    +rulesets-update-never = Never updated, or last update failed
    
    580
    +# Shown when the ruleset is disabled.
    
    581
    +rulesets-update-rule-disabled = Disabled
    
    582
    +
    
    583
    +## Ruleset details in about:rulesets. In Tor Browser, each ruleset is a set of rules for converting a ".tor.onion" address to a normal ".onion" address (used by SecureDrop). The feature is taken from the discontinued "HTTPS Everywhere".
    
    584
    +
    
    585
    +rulesets-details-edit-button = Edit
    
    586
    +rulesets-details-enable-checkbox = Enable this ruleset
    
    587
    +rulesets-details-update-button = Check for Updates
    
    588
    +rulesets-details-save-button = Save
    
    589
    +rulesets-details-cancel-button = Cancel
    
    590
    +# "JWK" refers to "JSON Web Key" and likely should not be translated.
    
    591
    +rulesets-details-jwk = JWK
    
    592
    +# "JWK" refers to "JSON Web Key" and likely should not be translated.
    
    593
    +rulesets-details-jwk-input =
    
    594
    +    .placeholder = The key used to sign this ruleset in the JWK (JSON Web Key) format
    
    595
    +# "JWK" refers to "JSON Web Key" and likely should not be translated.
    
    596
    +rulesets-details-jwk-input-invalid = The JWK could not be parsed, or it is not a valid key
    
    597
    +# "Path" refers to the URL domain this rule applies to.
    
    598
    +rulesets-details-path = Path Prefix
    
    599
    +rulesets-details-path-input =
    
    600
    +    .placeholder = URL prefix that contains the files needed by the ruleset
    
    601
    +# "HTTP(S)" refers to "HTTP or HTTPS".
    
    602
    +rulesets-details-path-input-invalid = The path prefix is not a valid HTTP(S) URL
    
    603
    +# "Scope" refers to the breadth of URLs this rule applies to (as a regular expression).
    
    604
    +rulesets-details-scope = Scope
    
    605
    +# "Regular expression" refers to the computing term for a special pattern used for matching: https://en.wikipedia.org/wiki/Regular_expression.
    
    606
    +rulesets-details-scope-input =
    
    607
    +    .placeholder = Regular expression for the scope of the rules
    
    608
    +# "Regular expression" refers to the computing term for a special pattern used for matching: https://en.wikipedia.org/wiki/Regular_expression.
    
    609
    +rulesets-details-scope-input-invalid = The scope could not be parsed as a regular expression

  • toolkit/modules/TorStrings.sys.mjs
    ... ... @@ -429,54 +429,6 @@ const Loader = {
    429 429
           learnMoreURLNotification: `https://tb-manual.torproject.org/${getLocale()}/onion-services/`,
    
    430 430
         };
    
    431 431
       } /* OnionLocation */,
    
    432
    -
    
    433
    -  /*
    
    434
    -    Rulesets
    
    435
    -  */
    
    436
    -  rulesets() {
    
    437
    -    const strings = {
    
    438
    -      // Initial warning
    
    439
    -      warningTitle: "Proceed with Caution",
    
    440
    -      warningDescription:
    
    441
    -        "Adding or modifying rulesets can cause attackers to hijack your browser. Proceed only if you know what you are doing.",
    
    442
    -      warningEnable: "Warn me when I attempt to access these preferences",
    
    443
    -      warningButton: "Accept the Risk and Continue",
    
    444
    -      // Ruleset list
    
    445
    -      rulesets: "Rulesets",
    
    446
    -      noRulesets: "No rulesets found",
    
    447
    -      noRulesetsDescr:
    
    448
    -        "When you save a ruleset in Tor Browser, it will show up here.",
    
    449
    -      lastUpdated: "Last updated %S",
    
    450
    -      neverUpdated: "Never updated, or last update failed",
    
    451
    -      enabled: "Enabled",
    
    452
    -      disabled: "Disabled",
    
    453
    -      // Ruleset details
    
    454
    -      edit: "Edit",
    
    455
    -      name: "Name",
    
    456
    -      jwk: "JWK",
    
    457
    -      pathPrefix: "Path Prefix",
    
    458
    -      scope: "Scope",
    
    459
    -      enable: "Enable this ruleset",
    
    460
    -      checkUpdates: "Check for Updates",
    
    461
    -      // Add ruleset
    
    462
    -      jwkPlaceholder:
    
    463
    -        "The key used to sign this ruleset in the JWK (JSON Web Key) format",
    
    464
    -      jwkInvalid: "The JWK could not be parsed, or it is not a valid key",
    
    465
    -      pathPrefixPlaceholder:
    
    466
    -        "URL prefix that contains the files needed by the ruleset",
    
    467
    -      pathPrefixInvalid: "The path prefix is not a valid HTTP(S) URL",
    
    468
    -      scopePlaceholder: "Regular expression for the scope of the rules",
    
    469
    -      scopeInvalid: "The scope could not be parsed as a regular expression",
    
    470
    -      save: "Save",
    
    471
    -      cancel: "Cancel",
    
    472
    -    };
    
    473
    -
    
    474
    -    const tsb = new TorPropertyStringBundle(
    
    475
    -      ["chrome://torbutton/locale/rulesets.properties"],
    
    476
    -      "rulesets."
    
    477
    -    );
    
    478
    -    return tsb.getStrings(strings);
    
    479
    -  } /* Rulesets */,
    
    480 432
     };
    
    481 433
     
    
    482 434
     export const TorStrings = {
    
    ... ... @@ -507,11 +459,4 @@ export const TorStrings = {
    507 459
         }
    
    508 460
         return this._onionLocation;
    
    509 461
       },
    
    510
    -
    
    511
    -  get rulesets() {
    
    512
    -    if (!this._rulesets) {
    
    513
    -      this._rulesets = Loader.rulesets();
    
    514
    -    }
    
    515
    -    return this._rulesets;
    
    516
    -  },
    
    517 462
     };

  • toolkit/torbutton/chrome/locale/en-US/rulesets.properties deleted
    1
    -# Copyright (c) 2022, The Tor Project, Inc.
    
    2
    -# This Source Code Form is subject to the terms of the Mozilla Public
    
    3
    -# License, v. 2.0. If a copy of the MPL was not distributed with this
    
    4
    -# file, You can obtain one at http://mozilla.org/MPL/2.0/.
    
    5
    -
    
    6
    -# about:rulesets strings.
    
    7
    -rulesets.warningTitle=Proceed with Caution
    
    8
    -rulesets.warningDescription=Adding or modifying rulesets can cause attackers to hijack your browser. Proceed only if you know what you are doing.
    
    9
    -rulesets.warningEnable=Warn me when I attempt to access these preferences
    
    10
    -rulesets.warningButton=Accept the Risk and Continue
    
    11
    -# Ruleset list
    
    12
    -rulesets.rulesets=Rulesets
    
    13
    -rulesets.noRulesets=No rulesets found
    
    14
    -rulesets.noRulesetsDescr=When you save a ruleset in Tor Browser, it will show up here.
    
    15
    -# LOCALIZATION NOTE: %S will be replaced by the update date (automatically formatted by Firefox's l10n component)
    
    16
    -rulesets.lastUpdated=Last updated %S
    
    17
    -rulesets.neverUpdated=Never updated, or last update failed
    
    18
    -rulesets.enabled=Enabled
    
    19
    -rulesets.disabled=Disabled
    
    20
    -# Ruleset details/edit ruleset
    
    21
    -rulesets.edit=Edit
    
    22
    -rulesets.name=Name
    
    23
    -rulesets.jwk=JWK
    
    24
    -rulesets.pathPrefix=Path Prefix
    
    25
    -rulesets.scope=Scope
    
    26
    -rulesets.enable=Enable this ruleset
    
    27
    -rulesets.checkUpdates=Check for Updates
    
    28
    -rulesets.jwkPlaceholder=The key used to sign this ruleset in the JWK (JSON Web Key) format
    
    29
    -rulesets.jwkInvalid=The JWK could not be parsed, or it is not a valid key
    
    30
    -rulesets.pathPrefixPlaceholder=URL prefix that contains the files needed by the ruleset
    
    31
    -rulesets.pathPrefixInvalid=The path prefix is not a valid HTTP(S) URL
    
    32
    -rulesets.scopePlaceholder=Regular expression for the scope of the rules
    
    33
    -rulesets.scopeInvalid=The scope could not be parsed as a regular expression
    
    34
    -rulesets.save=Save
    
    35
    -rulesets.cancel=Cancel

  • tools/torbrowser/l10n/migrations/bug-42206-rulesets.py
    1
    +import fluent.syntax.ast as FTL
    
    2
    +from fluent.migrate.helpers import transforms_from
    
    3
    +from fluent.migrate.transforms import REPLACE
    
    4
    +
    
    5
    +
    
    6
    +def migrate(ctx):
    
    7
    +    legacy_path = "rulesets.properties"
    
    8
    +
    
    9
    +    ctx.add_transforms(
    
    10
    +        "tor-browser.ftl",
    
    11
    +        "tor-browser.ftl",
    
    12
    +        transforms_from(
    
    13
    +            """
    
    14
    +rulesets-warning-heading = { COPY(path, "rulesets.warningTitle") }
    
    15
    +rulesets-warning-description = { COPY(path, "rulesets.warningDescription") }
    
    16
    +rulesets-warning-checkbox = { COPY(path, "rulesets.warningEnable") }
    
    17
    +rulesets-warning-continue-button = { COPY(path, "rulesets.warningButton") }
    
    18
    +
    
    19
    +rulesets-side-panel-heading = { COPY(path, "rulesets.rulesets") }
    
    20
    +rulesets-side-panel-no-rules = { COPY(path, "rulesets.noRulesets") }
    
    21
    +
    
    22
    +rulesets-update-never = { COPY(path, "rulesets.neverUpdated") }
    
    23
    +rulesets-update-rule-disabled = { COPY(path, "rulesets.disabled") }
    
    24
    +
    
    25
    +rulesets-details-edit-button = { COPY(path, "rulesets.edit") }
    
    26
    +rulesets-details-enable-checkbox = { COPY(path, "rulesets.enable") }
    
    27
    +rulesets-details-update-button = { COPY(path, "rulesets.checkUpdates") }
    
    28
    +rulesets-details-save-button = { COPY(path, "rulesets.save") }
    
    29
    +rulesets-details-cancel-button = { COPY(path, "rulesets.cancel") }
    
    30
    +rulesets-details-jwk-input =
    
    31
    +    .placeholder = { COPY(path, "rulesets.jwkPlaceholder") }
    
    32
    +rulesets-details-jwk-input-invalid = { COPY(path, "rulesets.jwkInvalid") }
    
    33
    +rulesets-details-path = { COPY(path, "rulesets.pathPrefix") }
    
    34
    +rulesets-details-path-input =
    
    35
    +    .placeholder = { COPY(path, "rulesets.pathPrefixPlaceholder") }
    
    36
    +rulesets-details-path-input-invalid = { COPY(path, "rulesets.pathPrefixInvalid") }
    
    37
    +rulesets-details-scope = { COPY(path, "rulesets.scope") }
    
    38
    +rulesets-details-scope-input =
    
    39
    +    .placeholder = { COPY(path, "rulesets.scopePlaceholder") }
    
    40
    +rulesets-details-scope-input-invalid = { COPY(path, "rulesets.scopeInvalid") }
    
    41
    +""",
    
    42
    +            path=legacy_path,
    
    43
    +        )
    
    44
    +        + [
    
    45
    +            # Replace "%1$S" with "{ DATETIME($date, dateStyle: "long") }"
    
    46
    +            FTL.Message(
    
    47
    +                FTL.Identifier("rulesets-update-last"),
    
    48
    +                value=REPLACE(
    
    49
    +                    legacy_path,
    
    50
    +                    "rulesets.lastUpdated",
    
    51
    +                    {
    
    52
    +                        "%1$S": FTL.FunctionReference(
    
    53
    +                            FTL.Identifier("DATETIME"),
    
    54
    +                            arguments=FTL.CallArguments(
    
    55
    +                                positional=[
    
    56
    +                                    FTL.VariableReference(FTL.Identifier("date"))
    
    57
    +                                ],
    
    58
    +                                named=[
    
    59
    +                                    FTL.NamedArgument(
    
    60
    +                                        FTL.Identifier("dateStyle"),
    
    61
    +                                        value=FTL.StringLiteral("long"),
    
    62
    +                                    )
    
    63
    +                                ],
    
    64
    +                            ),
    
    65
    +                        )
    
    66
    +                    },
    
    67
    +                ),
    
    68
    +            ),
    
    69
    +        ],
    
    70
    +    )