[tbb-commits] [tor-browser/tor-browser-91.6.0esr-11.0-1] Bug 25658: Replace security slider with security level UI

richard at torproject.org richard at torproject.org
Wed Feb 2 19:27:49 UTC 2022


commit 41ef39e812402bc803df11dbe1107425a1d565d3
Author: Richard Pospesel <richard at torproject.org>
Date:   Mon Mar 4 16:09:51 2019 -0800

    Bug 25658: Replace security slider with security level UI
    
    This patch adds a new 'securitylevel' component to Tor Browser intended
    to replace the torbutton 'Security Slider'.
    
    This component adds a new Security Level toolbar button which visually
    indicates the current global security level via icon (as defined by the
    extensions.torbutton.security_slider pref), a drop-down hanger with a
    short description of the current security level, and a new section in
    the about:preferences#privacy page where users can change their current
    security level. In addition, the hanger and the preferences page will
    show a visual warning when the user has modified prefs associated with
    the security level and provide a one-click 'Restore Defaults' button to
    get the user back on recommended settings.
    
    Strings used by this patch are pulled from the torbutton extension, but
    en-US defaults are provided if there is an error loading from the
    extension. With this patch applied, the usual work-flow of "./mach build
    && ./mach run" work as expected, even if the torbutton extension is
    disabled.
---
 browser/base/content/browser.js                    |  10 +
 browser/base/content/browser.xhtml                 |   2 +
 browser/base/content/main-popupset.inc.xhtml       |   1 +
 browser/base/content/navigator-toolbox.inc.xhtml   |   2 +
 browser/components/moz.build                       |   1 +
 browser/components/preferences/preferences.xhtml   |   1 +
 browser/components/preferences/privacy.inc.xhtml   |   2 +
 browser/components/preferences/privacy.js          |  19 +
 .../securitylevel/content/securityLevel.js         | 527 +++++++++++++++++++++
 .../securitylevel/content/securityLevelButton.css  |  18 +
 .../content/securityLevelButton.inc.xhtml          |   7 +
 .../securitylevel/content/securityLevelIcon.svg    |  40 ++
 .../securitylevel/content/securityLevelPanel.css   |  74 +++
 .../content/securityLevelPanel.inc.xhtml           |  47 ++
 .../content/securityLevelPreferences.css           |  52 ++
 .../content/securityLevelPreferences.inc.xhtml     |  67 +++
 browser/components/securitylevel/jar.mn            |   6 +
 browser/components/securitylevel/moz.build         |   1 +
 browser/modules/TorStrings.jsm                     |   4 +
 .../themes/shared/customizableui/panelUI.inc.css   |   3 +-
 20 files changed, 883 insertions(+), 1 deletion(-)

diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index eb7ec063f4b8..7c33ed9ebf3d 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -223,6 +223,11 @@ XPCOMUtils.defineLazyScriptGetter(
   ["DownloadsButton", "DownloadsIndicatorView"],
   "chrome://browser/content/downloads/indicator.js"
 );
+XPCOMUtils.defineLazyScriptGetter(
+  this,
+  ["SecurityLevelButton"],
+  "chrome://browser/content/securitylevel/securityLevel.js"
+);
 XPCOMUtils.defineLazyScriptGetter(
   this,
   "gEditItemOverlay",
@@ -1762,6 +1767,9 @@ var gBrowserInit = {
     // doesn't flicker as the window is being shown.
     DownloadsButton.init();
 
+    // Init the SecuritySettingsButton
+    SecurityLevelButton.init();
+
     // Certain kinds of automigration rely on this notification to complete
     // their tasks BEFORE the browser window is shown. SessionStore uses it to
     // restore tabs into windows AFTER important parts like gMultiProcessBrowser
@@ -2477,6 +2485,8 @@ var gBrowserInit = {
 
     DownloadsButton.uninit();
 
+    SecurityLevelButton.uninit();
+
     gAccessibilityServiceIndicator.uninit();
 
     if (gToolbarKeyNavEnabled) {
diff --git a/browser/base/content/browser.xhtml b/browser/base/content/browser.xhtml
index 8efb544918b8..8fbfa05196b0 100644
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -20,6 +20,8 @@
 <?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/tabbrowser.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/downloads/downloads.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/securitylevel/securityLevelPanel.css"?>
+<?xml-stylesheet href="chrome://browser/content/securitylevel/securityLevelButton.css"?>
 <?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/usercontext/usercontext.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
diff --git a/browser/base/content/main-popupset.inc.xhtml b/browser/base/content/main-popupset.inc.xhtml
index 835948482381..adf0a4f59e4b 100644
--- a/browser/base/content/main-popupset.inc.xhtml
+++ b/browser/base/content/main-popupset.inc.xhtml
@@ -519,6 +519,7 @@
 #include ../../components/controlcenter/content/protectionsPanel.inc.xhtml
 #include ../../components/downloads/content/downloadsPanel.inc.xhtml
 #include ../../../devtools/startup/enableDevToolsPopup.inc.xhtml
+#include ../../components/securitylevel/content/securityLevelPanel.inc.xhtml
 #include browser-allTabsMenu.inc.xhtml
 
   <tooltip id="dynamic-shortcut-tooltip"
diff --git a/browser/base/content/navigator-toolbox.inc.xhtml b/browser/base/content/navigator-toolbox.inc.xhtml
index 02636a6b46b5..efe981a74826 100644
--- a/browser/base/content/navigator-toolbox.inc.xhtml
+++ b/browser/base/content/navigator-toolbox.inc.xhtml
@@ -412,6 +412,8 @@
         </box>
       </toolbarbutton>
 
+#include ../../components/securitylevel/content/securityLevelButton.inc.xhtml
+
       <toolbarbutton id="fxa-toolbar-menu-button" class="toolbarbutton-1 chromeclass-toolbar-additional subviewbutton-nav"
                      badged="true"
                      onmousedown="gSync.toggleAccountPanel(this, event)"
diff --git a/browser/components/moz.build b/browser/components/moz.build
index c56811d36a14..becff6b356b3 100644
--- a/browser/components/moz.build
+++ b/browser/components/moz.build
@@ -49,6 +49,7 @@ DIRS += [
     "protocolhandler",
     "resistfingerprinting",
     "search",
+    "securitylevel",
     "sessionstore",
     "shell",
     "syncedtabs",
diff --git a/browser/components/preferences/preferences.xhtml b/browser/components/preferences/preferences.xhtml
index aab4a9e558bc..10faf11bfecd 100644
--- a/browser/components/preferences/preferences.xhtml
+++ b/browser/components/preferences/preferences.xhtml
@@ -12,6 +12,7 @@
 <?xml-stylesheet href="chrome://browser/skin/preferences/search.css"?>
 <?xml-stylesheet href="chrome://browser/skin/preferences/containers.css"?>
 <?xml-stylesheet href="chrome://browser/skin/preferences/privacy.css"?>
+<?xml-stylesheet href="chrome://browser/content/securitylevel/securityLevelPreferences.css"?>
 
 <!DOCTYPE html>
 
diff --git a/browser/components/preferences/privacy.inc.xhtml b/browser/components/preferences/privacy.inc.xhtml
index 8d51e60cb32b..d2cf2ea9c89c 100644
--- a/browser/components/preferences/privacy.inc.xhtml
+++ b/browser/components/preferences/privacy.inc.xhtml
@@ -919,6 +919,8 @@
   <html:h1 data-l10n-id="security-header"/>
 </hbox>
 
+#include ../securitylevel/content/securityLevelPreferences.inc.xhtml
+
 <!-- addons, forgery (phishing) UI Security -->
 <groupbox id="browsingProtectionGroup" data-category="panePrivacy" hidden="true">
   <label><html:h2 data-l10n-id="security-browsing-protection"/></label>
diff --git a/browser/components/preferences/privacy.js b/browser/components/preferences/privacy.js
index 35b37b099e93..42b899e0552f 100644
--- a/browser/components/preferences/privacy.js
+++ b/browser/components/preferences/privacy.js
@@ -80,6 +80,12 @@ XPCOMUtils.defineLazyGetter(this, "AlertsServiceDND", function() {
   }
 });
 
+XPCOMUtils.defineLazyScriptGetter(
+  this,
+  ["SecurityLevelPreferences"],
+  "chrome://browser/content/securitylevel/securityLevel.js"
+);
+
 XPCOMUtils.defineLazyServiceGetter(
   this,
   "listManager",
@@ -308,6 +314,18 @@ function setUpContentBlockingWarnings() {
 var gPrivacyPane = {
   _pane: null,
 
+  /**
+   * Show the Security Level UI
+   */
+  _initSecurityLevel() {
+    SecurityLevelPreferences.init();
+    let unload = () => {
+      window.removeEventListener("unload", unload);
+      SecurityLevelPreferences.uninit();
+    };
+    window.addEventListener("unload", unload);
+  },
+
   /**
    * Whether the prompt to restart Firefox should appear when changing the autostart pref.
    */
@@ -503,6 +521,7 @@ var gPrivacyPane = {
     this.trackingProtectionReadPrefs();
     this.networkCookieBehaviorReadPrefs();
     this._initTrackingProtectionExtensionControl();
+    this._initSecurityLevel();
 
     Services.telemetry.setEventRecordingEnabled("pwmgr", true);
 
diff --git a/browser/components/securitylevel/content/securityLevel.js b/browser/components/securitylevel/content/securityLevel.js
new file mode 100644
index 000000000000..8b8babe5b58e
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevel.js
@@ -0,0 +1,527 @@
+"use strict";
+
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+  CustomizableUI: "resource:///modules/CustomizableUI.jsm",
+  PanelMultiView: "resource:///modules/PanelMultiView.jsm",
+});
+
+ChromeUtils.defineModuleGetter(
+  this,
+  "TorStrings",
+  "resource:///modules/TorStrings.jsm"
+);
+
+/*
+  Security Level Prefs
+
+  Getters and Setters for relevant torbutton prefs
+*/
+const SecurityLevelPrefs = {
+  security_slider_pref : "extensions.torbutton.security_slider",
+  security_custom_pref : "extensions.torbutton.security_custom",
+
+  get securitySlider() {
+    try {
+      return Services.prefs.getIntPref(this.security_slider_pref);
+    } catch(e) {
+      // init pref to 4 (standard)
+      const val = 4;
+      Services.prefs.setIntPref(this.security_slider_pref, val);
+      return val;
+    }
+  },
+
+  set securitySlider(val) {
+    Services.prefs.setIntPref(this.security_slider_pref, val);
+  },
+
+  get securityCustom() {
+    try {
+      return Services.prefs.getBoolPref(this.security_custom_pref);
+    } catch(e) {
+      // init custom to false
+      const val = false;
+      Services.prefs.setBoolPref(this.security_custom_pref, val);
+      return val;
+    }
+  },
+
+  set securityCustom(val) {
+    Services.prefs.setBoolPref(this.security_custom_pref, val);
+  },
+}; /* Security Level Prefs */
+
+/*
+  Security Level Button Code
+
+  Controls init and update of the security level toolbar button
+*/
+
+const SecurityLevelButton = {
+  _securityPrefsBranch : null,
+
+  _populateXUL : function(securityLevelButton) {
+    if (securityLevelButton != null) {
+      securityLevelButton.setAttribute("tooltiptext", TorStrings.securityLevel.securityLevel);
+      securityLevelButton.setAttribute("label", TorStrings.securityLevel.securityLevel);
+    }
+  },
+
+  _configUIFromPrefs : function(securityLevelButton) {
+    if (securityLevelButton != null) {
+      let securitySlider = SecurityLevelPrefs.securitySlider;
+      securityLevelButton.removeAttribute("level");
+      const securityCustom = SecurityLevelPrefs.securityCustom;
+      switch(securitySlider) {
+        case 4:
+          securityLevelButton.setAttribute("level", `standard${securityCustom ? "_custom" : ""}`);
+          securityLevelButton.setAttribute("tooltiptext", TorStrings.securityLevel.standard.tooltip);
+          break;
+        case 2:
+          securityLevelButton.setAttribute("level", `safer${securityCustom ? "_custom" : ""}`);
+          securityLevelButton.setAttribute("tooltiptext", TorStrings.securityLevel.safer.tooltip);
+          break;
+        case 1:
+          securityLevelButton.setAttribute("level", `safest${securityCustom ? "_custom" : ""}`);
+          securityLevelButton.setAttribute("tooltiptext", TorStrings.securityLevel.safest.tooltip);
+          break;
+      }
+    }
+  },
+
+  get button() {
+    let button = document.getElementById("security-level-button");
+    if (!button) {
+      return null;
+    }
+    return button;
+  },
+
+  get anchor() {
+    let anchor = this.button.icon;
+    if (!anchor) {
+      return null;
+    }
+
+    anchor.setAttribute("consumeanchor", SecurityLevelButton.button.id);
+    return anchor;
+  },
+
+  init : function() {
+    // set the initial class based off of the current pref
+    let button = this.button;
+    this._populateXUL(button);
+    this._configUIFromPrefs(button);
+
+    this._securityPrefsBranch = Services.prefs.getBranch("extensions.torbutton.");
+    this._securityPrefsBranch.addObserver("", this, false);
+
+    CustomizableUI.addListener(this);
+
+    SecurityLevelPanel.init();
+  },
+
+  uninit : function() {
+    CustomizableUI.removeListener(this);
+
+    this._securityPrefsBranch.removeObserver("", this);
+    this._securityPrefsBranch = null;
+
+    SecurityLevelPanel.uninit();
+  },
+
+  observe : function(subject, topic, data) {
+    switch(topic) {
+      case "nsPref:changed":
+        if (data === "security_slider" || data === "security_custom") {
+          this._configUIFromPrefs(this.button);
+        }
+        break;
+    }
+  },
+
+  // callback for entering the 'Customize Firefox' screen to set icon
+  onCustomizeStart : function(window) {
+    let navigatorToolbox = document.getElementById("navigator-toolbox");
+    let button = navigatorToolbox.palette.querySelector("#security-level-button");
+    this._populateXUL(button);
+    this._configUIFromPrefs(button);
+  },
+
+  // callback when CustomizableUI modifies DOM
+  onWidgetAfterDOMChange : function(aNode, aNextNode, aContainer, aWasRemoval) {
+    if (aNode.id == "security-level-button" && !aWasRemoval) {
+      this._populateXUL(aNode);
+      this._configUIFromPrefs(aNode);
+    }
+  },
+
+  // for when the toolbar button needs to be activated and displays the Security Level panel
+  //
+  // In the toolbarbutton xul you'll notice we register this callback for both onkeypress and
+  // onmousedown. We do this to match the behavior of other panel spawning buttons such as Downloads,
+  // Library, and the Hamburger menus. Using oncommand alone would result in only getting fired
+  // after onclick, which is mousedown followed by mouseup.
+  onCommand : function(aEvent) {
+    // snippet borrowed from /browser/components/downloads/content/indicator.js DownloadsIndicatorView.onCommand(evt)
+    if (
+      // On Mac, ctrl-click will send a context menu event from the widget, so
+      // we don't want to bring up the panel when ctrl key is pressed.
+      (aEvent.type == "mousedown" &&
+        (aEvent.button != 0 ||
+          (AppConstants.platform == "macosx" && aEvent.ctrlKey))) ||
+      (aEvent.type == "keypress" && aEvent.key != " " && aEvent.key != "Enter")
+    ) {
+      return;
+    }
+
+    // we need to set this attribute for the button to be shaded correctly to look like it is pressed
+    // while the security level panel is open
+    this.button.setAttribute("open", "true");
+    SecurityLevelPanel.show();
+    aEvent.stopPropagation();
+  },
+}; /* Security Level Button */
+
+/*
+  Security Level Panel Code
+
+  Controls init and update of the panel in the security level hanger
+*/
+
+const SecurityLevelPanel = {
+  _securityPrefsBranch : null,
+  _panel : null,
+  _anchor : null,
+  _populated : false,
+
+  _selectors: Object.freeze({
+    panel: "panel#securityLevel-panel",
+    icon: "vbox#securityLevel-vbox>vbox",
+    header: "h1#securityLevel-header",
+    level: "label#securityLevel-level",
+    custom: "label#securityLevel-custom",
+    summary: "description#securityLevel-summary",
+    learnMore: "label#securityLevel-learnMore",
+    restoreDefaults: "button#securityLevel-restoreDefaults",
+    advancedSecuritySettings: "button#securityLevel-advancedSecuritySettings",
+  }),
+
+  _populateXUL : function() {
+    let selectors = this._selectors;
+
+    this._elements = {
+      panel: document.querySelector(selectors.panel),
+      icon: document.querySelector(selectors.icon),
+      header: document.querySelector(selectors.header),
+      levelLabel: document.querySelector(selectors.level),
+      customLabel: document.querySelector(selectors.custom),
+      summaryDescription: document.querySelector(selectors.summary),
+      learnMoreLabel: document.querySelector(selectors.learnMore),
+      restoreDefaultsButton: document.querySelector(selectors.restoreDefaults),
+      changeButton: document.querySelector(selectors.advancedSecuritySettings),
+    };
+    let elements = this._elements;
+
+    elements.header.textContent = TorStrings.securityLevel.securityLevel;
+    elements.customLabel.setAttribute("value", TorStrings.securityLevel.customWarning);
+    elements.learnMoreLabel.setAttribute("value", TorStrings.securityLevel.learnMore);
+    elements.learnMoreLabel.setAttribute("href", TorStrings.securityLevel.learnMoreURL);
+    elements.restoreDefaultsButton.setAttribute("label", TorStrings.securityLevel.restoreDefaults);
+    elements.changeButton.setAttribute("label", TorStrings.securityLevel.change);
+
+    this._configUIFromPrefs();
+    this._populated = true;
+  },
+
+  _configUIFromPrefs : function() {
+    // get security prefs
+    let securitySlider = SecurityLevelPrefs.securitySlider;
+    let securityCustom = SecurityLevelPrefs.securityCustom;
+
+    // get the panel elements we need to populate
+    let elements = this._elements;
+    let icon = elements.icon;
+    let labelLevel = elements.levelLabel;
+    let labelCustomWarning = elements.customLabel;
+    let summary = elements.summaryDescription;
+    let buttonRestoreDefaults = elements.restoreDefaultsButton;
+    let buttonAdvancedSecuritySettings = elements.changeButton;
+
+    // only visible when user is using custom settings
+    labelCustomWarning.hidden = !securityCustom;
+    buttonRestoreDefaults.hidden = !securityCustom;
+
+    // Descriptions change based on security level
+    switch(securitySlider) {
+      // standard
+      case 4:
+        icon.setAttribute("level", "standard");
+        labelLevel.setAttribute("value", TorStrings.securityLevel.standard.level);
+        summary.textContent = TorStrings.securityLevel.standard.summary;
+        break;
+      // safer
+      case 2:
+        icon.setAttribute("level", "safer");
+        labelLevel.setAttribute("value", TorStrings.securityLevel.safer.level);
+        summary.textContent = TorStrings.securityLevel.safer.summary;
+        break;
+      // safest
+      case 1:
+        icon.setAttribute("level", "safest");
+        labelLevel.setAttribute("value", TorStrings.securityLevel.safest.level);
+        summary.textContent = TorStrings.securityLevel.safest.summary;
+        break;
+    }
+
+    // override the summary text with custom warning
+    if (securityCustom) {
+      summary.textContent = TorStrings.securityLevel.custom.summary;
+    }
+  },
+
+  init : function() {
+    this._securityPrefsBranch = Services.prefs.getBranch("extensions.torbutton.");
+    this._securityPrefsBranch.addObserver("", this, false);
+  },
+
+  uninit : function() {
+    this._securityPrefsBranch.removeObserver("", this);
+    this._securityPrefsBranch = null;
+  },
+
+  show : function() {
+    // we have to defer this until after the browser has finished init'ing before
+    // we can populate the panel
+    if (!this._populated) {
+      this._populateXUL();
+    }
+
+    let panel = document.getElementById("securityLevel-panel");
+    panel.hidden = false;
+    PanelMultiView.openPopup(panel, SecurityLevelButton.anchor, "bottomcenter topright",
+                             0, 0, false, null).catch(Cu.reportError);
+  },
+
+  hide : function() {
+    let panel = document.getElementById("securityLevel-panel");
+    PanelMultiView.hidePopup(panel);
+  },
+
+  restoreDefaults : function() {
+    SecurityLevelPrefs.securityCustom = false;
+    // hide and reshow so that layout re-renders properly
+    this.hide();
+    this.show(this._anchor);
+  },
+
+  openAdvancedSecuritySettings : function() {
+    openPreferences("privacy-securitylevel");
+    this.hide();
+  },
+
+  // callback when prefs change
+  observe : function(subject, topic, data) {
+    switch(topic) {
+      case "nsPref:changed":
+        if (data == "security_slider" || data == "security_custom") {
+          this._configUIFromPrefs();
+        }
+        break;
+    }
+  },
+
+  // callback when the panel is displayed
+  onPopupShown : function(event) {
+    SecurityLevelButton.button.setAttribute("open", "true");
+  },
+
+  // callback when the panel is hidden
+  onPopupHidden : function(event) {
+    SecurityLevelButton.button.removeAttribute("open");
+  }
+}; /* Security Level Panel */
+
+/*
+  Security Level Preferences Code
+
+  Code to handle init and update of security level section in about:preferences#privacy
+*/
+
+const SecurityLevelPreferences =
+{
+  _securityPrefsBranch : null,
+
+  _populateXUL : function() {
+    let groupbox = document.getElementById("securityLevel-groupbox");
+
+    let labelHeader = groupbox.querySelector("#securityLevel-header");
+    labelHeader.textContent = TorStrings.securityLevel.securityLevel;
+
+    let spanOverview = groupbox.querySelector("#securityLevel-overview");
+    spanOverview.textContent = TorStrings.securityLevel.overview;
+
+    let labelLearnMore = groupbox.querySelector("#securityLevel-learnMore");
+    labelLearnMore.setAttribute("value", TorStrings.securityLevel.learnMore);
+    labelLearnMore.setAttribute("href", TorStrings.securityLevel.learnMoreURL);
+
+    let radiogroup =  document.getElementById("securityLevel-radiogroup");
+    radiogroup.addEventListener("command", SecurityLevelPreferences.selectSecurityLevel);
+
+    let populateRadioElements = function(vboxQuery, stringStruct) {
+      let vbox = groupbox.querySelector(vboxQuery);
+
+      let radio = vbox.querySelector("radio");
+      radio.setAttribute("label", stringStruct.level);
+
+      let customWarning = vbox.querySelector("#securityLevel-customWarning");
+      customWarning.setAttribute("value", TorStrings.securityLevel.customWarning);
+
+      let labelSummary = vbox.querySelector("#securityLevel-summary");
+      labelSummary.textContent = stringStruct.summary;
+
+      let labelRestoreDefaults = vbox.querySelector("#securityLevel-restoreDefaults");
+      labelRestoreDefaults.setAttribute("value", TorStrings.securityLevel.restoreDefaults);
+      labelRestoreDefaults.addEventListener("click",  SecurityLevelPreferences.restoreDefaults);
+
+      let description1 = vbox.querySelector("#securityLevel-description1");
+      if (description1) {
+        description1.textContent = stringStruct.description1;
+      }
+      let description2 = vbox.querySelector("#securityLevel-description2");
+      if (description2) {
+        description2.textContent = stringStruct.description2;
+      }
+      let description3 = vbox.querySelector("#securityLevel-description3");
+      if (description3) {
+        description3.textContent = stringStruct.description3;
+      }
+    };
+
+    populateRadioElements("#securityLevel-vbox-standard", TorStrings.securityLevel.standard);
+    populateRadioElements("#securityLevel-vbox-safer", TorStrings.securityLevel.safer);
+    populateRadioElements("#securityLevel-vbox-safest", TorStrings.securityLevel.safest);
+  },
+
+  _configUIFromPrefs : function() {
+    // read our prefs
+    let securitySlider = SecurityLevelPrefs.securitySlider;
+    let securityCustom = SecurityLevelPrefs.securityCustom;
+
+    // get our elements
+    let groupbox = document.getElementById("securityLevel-groupbox");
+
+    let radiogroup =  groupbox.querySelector("#securityLevel-radiogroup");
+    let labelStandardCustom = groupbox.querySelector("#securityLevel-vbox-standard label#securityLevel-customWarning");
+    let labelSaferCustom = groupbox.querySelector("#securityLevel-vbox-safer label#securityLevel-customWarning");
+    let labelSafestCustom = groupbox.querySelector("#securityLevel-vbox-safest label#securityLevel-customWarning");
+    let labelStandardRestoreDefaults = groupbox.querySelector("#securityLevel-vbox-standard label#securityLevel-restoreDefaults");
+    let labelSaferRestoreDefaults = groupbox.querySelector("#securityLevel-vbox-safer label#securityLevel-restoreDefaults");
+    let labelSafestRestoreDefaults = groupbox.querySelector("#securityLevel-vbox-safest label#securityLevel-restoreDefaults");
+
+    // hide custom label by default until we know which level we're at
+    labelStandardCustom.hidden = true;
+    labelSaferCustom.hidden = true;
+    labelSafestCustom.hidden = true;
+
+    labelStandardRestoreDefaults.hidden = true;
+    labelSaferRestoreDefaults.hidden = true;
+    labelSafestRestoreDefaults.hidden = true;
+
+    switch(securitySlider) {
+      // standard
+      case 4:
+        radiogroup.value = "standard";
+        labelStandardCustom.hidden = !securityCustom;
+        labelStandardRestoreDefaults.hidden = !securityCustom;
+        break;
+      // safer
+      case 2:
+        radiogroup.value = "safer";
+        labelSaferCustom.hidden = !securityCustom;
+        labelSaferRestoreDefaults.hidden = !securityCustom;
+        break;
+      // safest
+      case 1:
+        radiogroup.value = "safest";
+        labelSafestCustom.hidden = !securityCustom;
+        labelSafestRestoreDefaults.hidden = !securityCustom;
+        break;
+    }
+  },
+
+  init : function() {
+    // populate XUL with localized strings
+    this._populateXUL();
+
+    // read prefs and populate UI
+    this._configUIFromPrefs();
+
+    // register for pref chagnes
+    this._securityPrefsBranch = Services.prefs.getBranch("extensions.torbutton.");
+    this._securityPrefsBranch.addObserver("", this, false);
+  },
+
+  uninit : function() {
+    // unregister for pref change events
+    this._securityPrefsBranch.removeObserver("", this);
+    this._securityPrefsBranch = null;
+  },
+
+  // callback for when prefs change
+  observe : function(subject, topic, data) {
+    switch(topic) {
+      case "nsPref:changed":
+        if (data == "security_slider" ||
+            data == "security_custom") {
+          this._configUIFromPrefs();
+        }
+        break;
+    }
+  },
+
+  selectSecurityLevel : function() {
+    // radio group elements
+    let radiogroup =  document.getElementById("securityLevel-radiogroup");
+
+    // update pref based on selected radio option
+    switch (radiogroup.value) {
+      case "standard":
+        SecurityLevelPrefs.securitySlider = 4;
+        break;
+      case "safer":
+        SecurityLevelPrefs.securitySlider = 2;
+        break;
+      case "safest":
+        SecurityLevelPrefs.securitySlider = 1;
+        break;
+    }
+
+    SecurityLevelPreferences.restoreDefaults();
+  },
+
+  restoreDefaults : function() {
+    SecurityLevelPrefs.securityCustom = false;
+  },
+}; /* Security Level Prefereces */
+
+Object.defineProperty(this, "SecurityLevelButton", {
+  value: SecurityLevelButton,
+  enumerable: true,
+  writable: false
+});
+
+Object.defineProperty(this, "SecurityLevelPanel", {
+  value: SecurityLevelPanel,
+  enumerable: true,
+  writable: false
+});
+
+Object.defineProperty(this, "SecurityLevelPreferences", {
+  value: SecurityLevelPreferences,
+  enumerable: true,
+  writable: false
+});
diff --git a/browser/components/securitylevel/content/securityLevelButton.css b/browser/components/securitylevel/content/securityLevelButton.css
new file mode 100644
index 000000000000..38701250e9c9
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelButton.css
@@ -0,0 +1,18 @@
+toolbarbutton#security-level-button[level="standard"] {
+  list-style-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#standard");
+}
+toolbarbutton#security-level-button[level="safer"] {
+  list-style-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#safer");
+}
+toolbarbutton#security-level-button[level="safest"] {
+  list-style-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#safest");
+}
+toolbarbutton#security-level-button[level="standard_custom"] {
+  list-style-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#standard_custom");
+}
+toolbarbutton#security-level-button[level="safer_custom"] {
+  list-style-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#safer_custom");
+}
+toolbarbutton#security-level-button[level="safest_custom"] {
+  list-style-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#safest_custom");
+}
\ No newline at end of file
diff --git a/browser/components/securitylevel/content/securityLevelButton.inc.xhtml b/browser/components/securitylevel/content/securityLevelButton.inc.xhtml
new file mode 100644
index 000000000000..96ee1ec0ca49
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelButton.inc.xhtml
@@ -0,0 +1,7 @@
+<toolbarbutton id="security-level-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+               badged="true"
+               removable="true"
+               onmousedown="SecurityLevelButton.onCommand(event);"
+               onkeypress="SecurityLevelButton.onCommand(event);"
+               closemenu="none"
+               cui-areatype="toolbar"/>
diff --git a/browser/components/securitylevel/content/securityLevelIcon.svg b/browser/components/securitylevel/content/securityLevelIcon.svg
new file mode 100644
index 000000000000..38cdbcb68afc
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelIcon.svg
@@ -0,0 +1,40 @@
+<svg width="16" height="16" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <style>
+    use:not(:target) {
+      display: none;
+    }
+  </style>
+  <defs>
+    <g id="standard_icon" stroke="none" stroke-width="1">
+      <path clip-rule="evenodd" d="m8.49614.283505c-.30743-.175675-.68485-.175675-.99228.000001l-6 3.428574c-.31157.17804-.50386.50938-.50386.86824v1.41968c0 4 2.98667 9.0836 7 10 4.0133-.9164 7-6 7-10v-1.41968c0-.35886-.1923-.6902-.5039-.86824zm-.49614 1.216495-5.75 3.28571v1.2746c0 1.71749.65238 3.7522 1.78726 5.46629 1.07287 1.6204 2.47498 2.8062 3.96274 3.2425 1.48776-.4363 2.8899-1.6221 3.9627-3.2425 1.1349-1.71409 1.7873-3.7488 1.7873-5.46629v-1.2746z" fill-rule="evenodd" />
+    </g>
+    <g id="safer_icon" stroke="none" stroke-width="1">
+      <path clip-rule="evenodd" d="m8.49614.283505c-.30743-.175675-.68485-.175675-.99228.000001l-6 3.428574c-.31157.17804-.50386.50938-.50386.86824v1.41968c0 4 2.98667 9.0836 7 10 4.0133-.9164 7-6 7-10v-1.41968c0-.35886-.1923-.6902-.5039-.86824zm-.49614 1.216495-5.75 3.28571v1.2746c0 1.71749.65238 3.7522 1.78726 5.46629 1.07287 1.6204 2.47498 2.8062 3.96274 3.2425 1.48776-.4363 2.8899-1.6221 3.9627-3.2425 1.1349-1.71409 1.7873-3.7488 1.7873-5.46629v-1.2746z" fill-rule="evenodd"/>
+      <path d="m3.5 6.12062v-.40411c0-.08972.04807-.17255.12597-.21706l4-2.28572c.16666-.09523.37403.02511.37403.21707v10.0766c-1.01204-.408-2.054-1.3018-2.92048-2.6105-1.02134-1.54265-1.57952-3.34117-1.57952-4.77628z"/>
+    </g>
+    <g id="safest_icon" stroke="none" stroke-width="1">
+      <path clip-rule="evenodd" d="m8.49614.283505c-.30743-.175675-.68485-.175675-.99228.000001l-6 3.428574c-.31157.17804-.50386.50938-.50386.86824v1.41968c0 4 2.98667 9.0836 7 10 4.0133-.9164 7-6 7-10v-1.41968c0-.35886-.1923-.6902-.5039-.86824zm-.49614 1.216495-5.75 3.28571v1.2746c0 1.71749.65238 3.7522 1.78726 5.46629 1.07287 1.6204 2.47498 2.8062 3.96274 3.2425 1.48776-.4363 2.8899-1.6221 3.9627-3.2425 1.1349-1.71409 1.7873-3.7488 1.7873-5.46629v-1.2746z" fill-rule="evenodd"/>
+      <path d="m3.5 6.12062v-.40411c0-.08972.04807-.17255.12597-.21706l4.25-2.42857c.07685-.04392.17121-.04392.24806 0l4.24997 2.42857c.0779.04451.126.12734.126.21706v.40411c0 1.43511-.5582 3.23363-1.5795 4.77628-.8665 1.3087-1.90846 2.2025-2.9205 2.6105-1.01204-.408-2.054-1.3018-2.92048-2.6105-1.02134-1.54265-1.57952-3.34117-1.57952-4.77628z"/>
+    </g>
+    <g id="standard_custom_icon" stroke="none" stroke-width="1">
+      <path d="m9.37255.784312-.87641-.500806c-.30743-.175676-.68485-.175676-.99228 0l-6 3.428574c-.31157.17804-.50386.50938-.50386.86824v1.41968c0 4 2.98667 9.0836 7 10 3.7599-.8585 6.6186-5.3745 6.9647-9.23043-.4008.20936-.8392.35666-1.3024.42914-.2132 1.43414-.8072 2.98009-1.6996 4.32789-1.0728 1.6204-2.47494 2.8062-3.9627 3.2425-1.48776-.4363-2.88987-1.6221-3.96274-3.2425-1.13488-1.71409-1.78726-3.7488-1.78726-5.46629v-1.2746l5.75-3.28571.86913.49664c.10502-.43392.27664-.84184.50342-1.212328z"/>
+      <circle cx="13" cy="3" fill="#ffbd2e" r="3"/>
+    </g>
+    <g id="safer_custom_icon" stroke="none" stroke-width="1">
+      <path d="m9.37255.784312-.87641-.500806c-.30743-.175676-.68485-.175676-.99228 0l-6 3.428574c-.31157.17804-.50386.50938-.50386.86824v1.41968c0 4 2.98667 9.0836 7 10 3.7599-.8585 6.6186-5.3745 6.9647-9.23043-.4008.20936-.8392.35666-1.3024.42914-.2132 1.43414-.8072 2.98009-1.6996 4.32789-1.0728 1.6204-2.47494 2.8062-3.9627 3.2425-1.48776-.4363-2.88987-1.6221-3.96274-3.2425-1.13488-1.71409-1.78726-3.7488-1.78726-5.46629v-1.2746l5.75-3.28571.86913.49664c.10502-.43392.27664-.84184.50342-1.212328z"/>
+      <path d="m3.5 6.12062v-.40411c0-.08972.04807-.17255.12597-.21706l4-2.28572c.16666-.09523.37403.02511.37403.21707v10.0766c-1.01204-.408-2.054-1.3018-2.92048-2.6105-1.02134-1.54265-1.57952-3.34117-1.57952-4.77628z"/>
+      <circle cx="13" cy="3" fill="#ffbd2e" r="3"/>
+    </g>
+    <g id="safest_custom_icon" stroke="none" stroke-width="1">
+      <path d="m9.37255.784312-.87641-.500806c-.30743-.175676-.68485-.175676-.99228 0l-6 3.428574c-.31157.17804-.50386.50938-.50386.86824v1.41968c0 4 2.98667 9.0836 7 10 3.7599-.8585 6.6186-5.3745 6.9647-9.23043-.4008.20936-.8392.35666-1.3024.42914-.2132 1.43414-.8072 2.98009-1.6996 4.32789-1.0728 1.6204-2.47494 2.8062-3.9627 3.2425-1.48776-.4363-2.88987-1.6221-3.96274-3.2425-1.13488-1.71409-1.78726-3.7488-1.78726-5.46629v-1.2746l5.75-3.28571.86913.49664c.10502-.43392.27664-.84184.50342-1.212328z"/>
+      <path d="m8.77266 3.44151-.64863-.37064c-.07685-.04392-.17121-.04392-.24806 0l-4.25 2.42857c-.0779.04451-.12597.12735-.12597.21706v.40412c0 1.4351.55818 3.23362 1.57952 4.77618.86648 1.3087 1.90844 2.2026 2.92048 2.6106 1.01204-.408 2.054-1.3018 2.9205-2.6106.7761-1.17217 1.2847-2.49215 1.4843-3.68816-1.9219-.26934-3.43158-1.82403-3.63214-3.76713z"/>
+      <circle cx="13" cy="3" fill="#ffbd2e" r="3"/>
+    </g>
+  </defs>
+  <use id="standard" fill="context-fill" fill-opacity="context-fill-opacity" href="#standard_icon" />
+  <use id="safer" fill="context-fill" fill-opacity="context-fill-opacity" href="#safer_icon" />
+  <use id="safest" fill="context-fill" fill-opacity="context-fill-opacity" href="#safest_icon" />
+  <use id="standard_custom" fill="context-fill" fill-opacity="context-fill-opacity" href="#standard_custom_icon" />
+  <use id="safer_custom" fill="context-fill" fill-opacity="context-fill-opacity" href="#safer_custom_icon" />
+  <use id="safest_custom" fill="context-fill" fill-opacity="context-fill-opacity" href="#safest_custom_icon" />
+</svg>
diff --git a/browser/components/securitylevel/content/securityLevelPanel.css b/browser/components/securitylevel/content/securityLevelPanel.css
new file mode 100644
index 000000000000..6462c02f1594
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelPanel.css
@@ -0,0 +1,74 @@
+/* Security Level CSS */
+
+panelview#securityLevel-panelview {
+  width: 25em;
+}
+
+vbox#securityLevel-vbox > vbox {
+  background-repeat: no-repeat;
+  /* icon center-line should be in-line with right margin */
+  /* -margin + panelWidth - imageWidth/2 */
+  background-position: calc(-16px + 25em - 4.5em) 0.4em;
+  background-size: 9em 9em;
+  -moz-context-properties: fill, fill-opacity;
+  fill-opacity: 1;
+  fill: var(--button-bgcolor);
+  min-height: 10em;
+}
+
+vbox#securityLevel-vbox > vbox[level="standard"] {
+  background-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#standard");
+}
+vbox#securityLevel-vbox > vbox[level="safer"] {
+  background-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#safer");
+}
+vbox#securityLevel-vbox > vbox[level="safest"] {
+  background-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#safest");
+}
+
+vbox#securityLevel-vbox > toolbarseparator {
+  margin-inline: 16px;
+}
+
+vbox#securityLevel-vbox > vbox {
+  margin-inline: 0;
+  padding-inline: 16px;
+}
+
+vbox#securityLevel-vbox > vbox * {
+  margin-inline: 0;
+}
+
+vbox#securityLevel-vbox > vbox > hbox {
+}
+
+label#securityLevel-level {
+  font-size: 1.25em;
+  font-weight: 600;
+  padding-top: 0.15em;
+}
+
+label#securityLevel-custom {
+  border-radius: 4px;
+  background-color: var(--yellow-50);
+  color: black;
+  font-size: 1em;
+  height: 1.6em;
+  line-height: 1.0em;
+  padding: 0.4em 0.5em;
+  margin-left: 1em!important;
+}
+
+description#securityLevel-summary {
+  margin-top: 1em;
+  padding-right: 5em;
+}
+
+vbox#securityLevel-vbox > hbox.panel-footer {
+  display: flex;
+}
+
+
+button#securityLevel-advancedSecuritySettings {
+  margin-block: 0;
+}
diff --git a/browser/components/securitylevel/content/securityLevelPanel.inc.xhtml b/browser/components/securitylevel/content/securityLevelPanel.inc.xhtml
new file mode 100644
index 000000000000..02d93b738ff5
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelPanel.inc.xhtml
@@ -0,0 +1,47 @@
+<panel id="securityLevel-panel"
+       role="group"
+       type="arrow"
+       orient="vertical"
+       level="top"
+       hidden="true"
+       class="panel-no-padding"
+       onpopupshown="SecurityLevelPanel.onPopupShown(event);"
+       onpopuphidden="SecurityLevelPanel.onPopupHidden(event);">
+  <panelmultiview mainViewId="securityLevel-panelview">
+    <panelview id="securityLevel-panelview" descriptionheightworkaround="true">
+      <vbox id="securityLevel-vbox">
+        <box class="panel-header">
+          <html:h1 id="securityLevel-header"/>
+        </box>
+        <toolbarseparator></toolbarseparator>
+        <vbox>
+          <hbox>
+            <label id="securityLevel-level"/>
+            <vbox>
+              <spacer flex="1"/>
+              <label id="securityLevel-custom"/>
+              <spacer flex="1"/>
+            </vbox>
+            <spacer flex="1"/>
+          </hbox>
+          <description id="securityLevel-summary"/>
+          <hbox>
+            <label
+              id="securityLevel-learnMore"
+              class="learnMore text-link"
+              onclick="SecurityLevelPanel.hide();"
+              is="text-link"/>
+            <spacer/>
+          </hbox>
+        </vbox>
+        <hbox class="panel-footer">
+            <button id="securityLevel-restoreDefaults"
+                    oncommand="SecurityLevelPanel.restoreDefaults();"/>
+            <button id="securityLevel-advancedSecuritySettings"
+                    default="true"
+                    oncommand="SecurityLevelPanel.openAdvancedSecuritySettings();"/>
+        </hbox>
+      </vbox>
+    </panelview>
+  </panelmultiview>
+</panel>
diff --git a/browser/components/securitylevel/content/securityLevelPreferences.css b/browser/components/securitylevel/content/securityLevelPreferences.css
new file mode 100644
index 000000000000..12a7cccffe09
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelPreferences.css
@@ -0,0 +1,52 @@
+label#securityLevel-customWarning {
+  border-radius: 4px;
+  background-color: var(--yellow-50);
+  color: black;
+  font-size: 1em;
+  height: 1.6em;
+  padding: 0.4em 0.5em;
+}
+
+radiogroup#securityLevel-radiogroup description {
+  color: var(--in-content-page-color)!important;
+}
+
+radiogroup#securityLevel-radiogroup radio {
+  font-weight: bold;
+}
+
+radiogroup#securityLevel-radiogroup > vbox {
+  border: 1px solid var(--in-content-box-border-color);
+  border-radius: 4px;
+  margin: 3px 0;
+  padding: 9px;
+}
+
+radiogroup#securityLevel-radiogroup[value=standard] > vbox#securityLevel-vbox-standard,
+radiogroup#securityLevel-radiogroup[value=safer] > vbox#securityLevel-vbox-safer,
+radiogroup#securityLevel-radiogroup[value=safest] > vbox#securityLevel-vbox-safest {
+  --section-highlight-background-color: color-mix(in srgb, var(--in-content-accent-color) 20%, transparent);
+  background-color: var(--section-highlight-background-color);
+  border: 1px solid var(--in-content-accent-color);
+
+}
+
+vbox#securityLevel-descriptionList {
+  display: none;
+  margin-inline-start:
+}
+
+radiogroup#securityLevel-radiogroup[value=safer] > vbox#securityLevel-vbox-safer > vbox#securityLevel-descriptionList,
+radiogroup#securityLevel-radiogroup[value=safest] > vbox#securityLevel-vbox-safest > vbox#securityLevel-descriptionList {
+  display: inherit;
+}
+
+vbox#securityLevel-descriptionList > description {
+  display: list-item;
+}
+
+vbox#securityLevel-vbox-standard,
+vbox#securityLevel-vbox-safer,
+vbox#securityLevel-vbox-safest {
+  margin-top: 0.4em;
+}
diff --git a/browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml b/browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml
new file mode 100644
index 000000000000..b050dad81621
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml
@@ -0,0 +1,67 @@
+<groupbox id="securityLevel-groupbox" data-category="panePrivacy" hidden="true">
+  <label><html:h2 id="securityLevel-header"/></label>
+  <vbox data-subcategory="securitylevel" flex="1">
+    <description flex="1">
+      <html:span id="securityLevel-overview" class="tail-with-learn-more"/>
+      <label id="securityLevel-learnMore" class="learnMore text-link" is="text-link"/>
+    </description>
+    <radiogroup id="securityLevel-radiogroup">
+      <vbox id="securityLevel-vbox-standard">
+        <hbox>
+          <radio value="standard"/>
+          <vbox>
+            <spacer flex="1"/>
+            <label id="securityLevel-customWarning"/>
+            <spacer flex="1"/>
+          </vbox>
+          <spacer flex="1"/>
+        </hbox>
+        <description flex="1" class="indent">
+          <html:span id="securityLevel-summary" class="tail-with-learn-more"/>
+          <label id="securityLevel-restoreDefaults"
+                 class="learnMore text-link"/>
+        </description>
+      </vbox>
+      <vbox id="securityLevel-vbox-safer">
+        <hbox>
+          <radio value="safer"/>
+          <vbox>
+            <spacer flex="1"/>
+            <label id="securityLevel-customWarning"/>
+            <spacer flex="1"/>
+          </vbox>
+        </hbox>
+        <description flex="1" class="indent">
+          <html:span id="securityLevel-summary" class="tail-with-learn-more"/>
+          <label id="securityLevel-restoreDefaults"
+                 class="learnMore text-link"/>
+        </description>
+        <vbox id="securityLevel-descriptionList" class="indent">
+          <description id="securityLevel-description1" class="indent"/>
+          <description id="securityLevel-description2" class="indent"/>
+          <description id="securityLevel-description3" class="indent"/>
+        </vbox>
+      </vbox>
+      <vbox id="securityLevel-vbox-safest">
+        <hbox>
+          <radio value="safest"/>
+          <vbox>
+            <spacer flex="1"/>
+            <label id="securityLevel-customWarning"/>
+            <spacer flex="1"/>
+          </vbox>
+        </hbox>
+        <description flex="1" class="indent">
+          <html:span id="securityLevel-summary" class="tail-with-learn-more"/>
+          <label id="securityLevel-restoreDefaults"
+                 class="learnMore text-link"/>
+        </description>
+        <vbox id="securityLevel-descriptionList" class="indent">
+          <description id="securityLevel-description1" class="indent"/>
+          <description id="securityLevel-description2" class="indent"/>
+          <description id="securityLevel-description3" class="indent"/>
+        </vbox>
+      </vbox>
+    </radiogroup>
+  </vbox>
+</groupbox>
diff --git a/browser/components/securitylevel/jar.mn b/browser/components/securitylevel/jar.mn
new file mode 100644
index 000000000000..61aa4169f9ec
--- /dev/null
+++ b/browser/components/securitylevel/jar.mn
@@ -0,0 +1,6 @@
+browser.jar:
+    content/browser/securitylevel/securityLevel.js             (content/securityLevel.js)
+    content/browser/securitylevel/securityLevelPanel.css       (content/securityLevelPanel.css)
+    content/browser/securitylevel/securityLevelButton.css      (content/securityLevelButton.css)
+    content/browser/securitylevel/securityLevelPreferences.css (content/securityLevelPreferences.css)
+    content/browser/securitylevel/securityLevelIcon.svg        (content/securityLevelIcon.svg)
diff --git a/browser/components/securitylevel/moz.build b/browser/components/securitylevel/moz.build
new file mode 100644
index 000000000000..2661ad7cb9f3
--- /dev/null
+++ b/browser/components/securitylevel/moz.build
@@ -0,0 +1 @@
+JAR_MANIFESTS += ["jar.mn"]
diff --git a/browser/modules/TorStrings.jsm b/browser/modules/TorStrings.jsm
index e8a8d37ae373..32dab2bfc6bf 100644
--- a/browser/modules/TorStrings.jsm
+++ b/browser/modules/TorStrings.jsm
@@ -182,6 +182,10 @@ var TorStrings = {
         "advanced_security_settings",
         "Advanced Security Settings\u2026"
       ),
+      change: getString(
+        "change",
+        "Change\u2026"
+      ),
     };
     return retval;
   })() /* Security Level Strings */,
diff --git a/browser/themes/shared/customizableui/panelUI.inc.css b/browser/themes/shared/customizableui/panelUI.inc.css
index e1d64c707518..abecf34cdb92 100644
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -1430,7 +1430,8 @@ menuitem.panel-subview-footer at menuStateActive@,
 #editBookmarkPanel toolbarseparator,
 #downloadsPanel-mainView toolbarseparator,
 .cui-widget-panelview menuseparator,
-.cui-widget-panel toolbarseparator {
+.cui-widget-panel toolbarseparator,
+#securityLevel-panel toolbarseparator {
   appearance: none;
   min-height: 0;
   border-top: 1px solid var(--panel-separator-color);





More information about the tbb-commits mailing list