[tor-commits] [tor-browser/tor-browser-83.0-10.0-1] Bug 25658: Replace security slider with security level UI

sysrqb at torproject.org sysrqb at torproject.org
Thu Nov 26 14:53:02 UTC 2020


commit 74083443f5c24774d3bc08fe745c7979e6d4d56c
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                 |   5 +
 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         | 501 +++++++++++++++++++++
 .../securitylevel/content/securityLevelButton.css  |   9 +
 .../content/securityLevelButton.inc.xhtml          |   7 +
 .../securitylevel/content/securityLevelButton.svg  |  21 +
 .../securitylevel/content/securityLevelPanel.css   |  82 ++++
 .../content/securityLevelPanel.inc.xhtml           |  38 ++
 .../content/securityLevelPreferences.css           |  26 ++
 .../content/securityLevelPreferences.inc.xhtml     |  62 +++
 browser/components/securitylevel/jar.mn            |   6 +
 browser/components/securitylevel/moz.build         |   1 +
 16 files changed, 791 insertions(+)

diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index da1d1d869209..5203a6179f55 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -215,6 +215,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",
@@ -1851,6 +1856,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
@@ -2533,6 +2541,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 4986e6d97841..96c93bac9b43 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"?>
@@ -644,6 +646,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
 
     <hbox id="downloads-animation-container">
@@ -1981,6 +1984,8 @@
             </stack>
           </toolbarbutton>
 
+#include ../../components/securitylevel/content/securityLevelButton.inc.xhtml
+
         <toolbarbutton id="library-button" class="toolbarbutton-1 chromeclass-toolbar-additional subviewbutton-nav"
                        removable="true"
                        onmousedown="PanelUI.showSubView('appMenu-libraryView', this, event);"
diff --git a/browser/components/moz.build b/browser/components/moz.build
index 0bd5fd264633..226eab0d3265 100644
--- a/browser/components/moz.build
+++ b/browser/components/moz.build
@@ -51,6 +51,7 @@ DIRS += [
     'protocolhandler',
     'resistfingerprinting',
     'search',
+    'securitylevel',
     'sessionstore',
     'shell',
     'ssb',
diff --git a/browser/components/preferences/preferences.xhtml b/browser/components/preferences/preferences.xhtml
index 99d5ae9892a5..b1e08364e1cc 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 ef3369d4250e..cac332fc69a9 100644
--- a/browser/components/preferences/privacy.inc.xhtml
+++ b/browser/components/preferences/privacy.inc.xhtml
@@ -906,6 +906,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 b6d9d7ee5ded..30539da603ce 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",
@@ -282,6 +288,18 @@ function addCustomBlockingLearnMore() {
 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.
    */
@@ -493,6 +511,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..b47d0cfb545e
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevel.js
@@ -0,0 +1,501 @@
+"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;
+      let classList = securityLevelButton.classList;
+      classList.remove("standard", "safer", "safest");
+      switch(securitySlider) {
+        case 4:
+          classList.add("standard");
+          securityLevelButton.setAttribute("tooltiptext", TorStrings.securityLevel.standard.tooltip);
+          break;
+        case 2:
+          classList.add("safer");
+          securityLevelButton.setAttribute("tooltiptext", TorStrings.securityLevel.safer.tooltip);
+          break;
+        case 1:
+          classList.add("safest");
+          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") {
+          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 stolen from /browser/components/downloads/indicator.js DownloadsIndicatorView.onCommand(evt)
+    if (
+      (aEvent.type == "mousedown" && aEvent.button != 0) ||
+      (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();
+  },
+}; /* 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,
+
+  _populateXUL : function() {
+    // get the panel elements we need to populate
+    let panelview = document.getElementById("securityLevel-panelview");
+    let labelHeader = panelview.querySelector("#securityLevel-header");
+    let labelCustomWarning = panelview.querySelector("#securityLevel-customWarning")
+    let labelLearnMore = panelview.querySelector("#securityLevel-learnMore");
+    let buttonRestoreDefaults = panelview.querySelector("#securityLevel-restoreDefaults");
+    let buttonAdvancedSecuritySettings = panelview.querySelector("#securityLevel-advancedSecuritySettings");
+
+    labelHeader.setAttribute("value", TorStrings.securityLevel.securityLevel);
+    labelCustomWarning.setAttribute("value", TorStrings.securityLevel.customWarning);
+    labelLearnMore.setAttribute("value", TorStrings.securityLevel.learnMore);
+    labelLearnMore.setAttribute("href", TorStrings.securityLevel.learnMoreURL);
+    buttonRestoreDefaults.setAttribute("label", TorStrings.securityLevel.restoreDefaults);
+    buttonAdvancedSecuritySettings.setAttribute("label", TorStrings.securityLevel.advancedSecuritySettings);
+
+    // rest of the XUL is set based on security prefs
+    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 panelview = document.getElementById("securityLevel-panelview");
+    let labelLevel = panelview.querySelector("#securityLevel-level");
+    let labelCustomWarning = panelview.querySelector("#securityLevel-customWarning")
+    let summary = panelview.querySelector("#securityLevel-summary");
+    let buttonRestoreDefaults = panelview.querySelector("#securityLevel-restoreDefaults");
+    let buttonAdvancedSecuritySettings = panelview.querySelector("#securityLevel-advancedSecuritySettings");
+
+    // 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:
+        labelLevel.setAttribute("value", TorStrings.securityLevel.standard.level);
+        summary.textContent = TorStrings.securityLevel.standard.summary;
+        break;
+      // safer
+      case 2:
+        labelLevel.setAttribute("value", TorStrings.securityLevel.safer.level);
+        summary.textContent = TorStrings.securityLevel.safer.summary;
+        break;
+      // safest
+      case 1:
+        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..81f2365bae28
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelButton.css
@@ -0,0 +1,9 @@
+toolbarbutton#security-level-button.standard {
+  list-style-image: url("chrome://browser/content/securitylevel/securityLevelButton.svg#standard");
+}
+toolbarbutton#security-level-button.safer {
+  list-style-image: url("chrome://browser/content/securitylevel/securityLevelButton.svg#safer");
+}
+toolbarbutton#security-level-button.safest {
+  list-style-image: url("chrome://browser/content/securitylevel/securityLevelButton.svg#safest");
+}
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/securityLevelButton.svg b/browser/components/securitylevel/content/securityLevelButton.svg
new file mode 100644
index 000000000000..8535cdcc531e
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelButton.svg
@@ -0,0 +1,21 @@
+<svg width="14px" height="16px" viewBox="0 0 14 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 d="M7.0 2.16583509C7.0 2.16583509 2.0 4.24375717 2.0 4.24375717C2.0 4.24375717 2.0 7.27272727 2.0 7.27272727C2.0 10.2413541 4.13435329 13.0576771 7.0 13.9315843C9.8656467 13.0576771 12.0 10.2413541 12.0 7.27272727C12.0 7.27272727 12.0 4.24375717 12.0 4.24375717C12.0 4.24375717 7.0 2.16583509 7.0 2.16583509C7.0 2.16583509 7.0 2.16583509 7.0 2.16583509M7.0 0.0C7.0 0.0 14.0 2.90909091 14.0 2.90909091C14.0 2.90909091 14.0 7.27272727 14.0 7.27272727C14.0 11.3090909 11.0133333 15.0836364 7.0 16.0C2.98666667 15.0836364 0.0 11.3090909 0.0 7.27272727C0.0 7.27272727 0.0 2.90909091 0.0 2.90909091C0.0 2.90909091 7.0 0.0 7.0 0.0C7.0 0.0 7.0 0.0 7.0 0.0" />
+    </g>
+    <g id="safer_icon" stroke="none" stroke-width="1">
+      <path fill-rule="nonzero" d="M7.0 2.1658351C7.0 13.931584 7.0 2.1658351 7.0 13.931584C9.8656467 13.057677 12.0 10.241354 12.0 7.2727273C12.0 7.2727273 12.0 4.2437572 12.0 4.2437572C12.0 4.2437572 7.0 2.1658351 7.0 2.1658351C7.0 2.1658351 7.0 2.1658351 7.0 2.1658351M7.0 0.0C7.0 0.0 14.0 2.9090909 14.0 2.9090909C14.0 2.9090909 14.0 7.2727273 14.0 7.2727273C14.0 11.309091 11.013333 15.083636 7.0 16.0C2.9866667 15.083636 0.0 11.309091 0.0 7.2727273C0.0 7.2727273 0.0 2.9090909 0.0 2.9090909C0.0 2.9090909 7.0 0.0 7.0 0.0"/>
+    </g>
+    <g id="safest_icon" stroke="none" stroke-width="1">
+      <path d="M7.0 0.0C7.0 0.0 14.0 2.90909091 14.0 2.90909091C14.0 2.90909091 14.0 7.27272727 14.0 7.27272727C14.0 11.3090909 11.0133333 15.0836364 7.0 16.0C2.98666667 15.0836364 0.0 11.3090909 0.0 7.27272727C0.0 7.27272727 0.0 2.90909091 0.0 2.90909091C0.0 2.90909091 7.0 0.0 7.0 0.0C7.0 0.0 7.0 0.0 7.0 0.0" />
+    </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" />
+</svg>
diff --git a/browser/components/securitylevel/content/securityLevelPanel.css b/browser/components/securitylevel/content/securityLevelPanel.css
new file mode 100644
index 000000000000..70022e2bd4b2
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelPanel.css
@@ -0,0 +1,82 @@
+/* Security Level CSS */
+
+panel#securityLevel-panel > .panel-arrowcontainer > .panel-arrowcontent {
+  padding: 0;
+}
+
+panelview#securityLevel-panelview {
+  width: 20em;
+}
+
+panelview#securityLevel-panelview>vbox.panel-subview-body {
+  padding: 1em;
+}
+
+label#securityLevel-header {
+  text-transform: uppercase;
+  color: var(--panel-disabled-color);
+  font-size: 0.85em;
+  margin: 0 0 0.4em 0;
+  padding: 0;
+}
+
+hbox#securityLevel-levelHbox {
+  margin-bottom: 1em;
+}
+
+label#securityLevel-level {
+  font-size: 1.5em;
+  margin: 0 0.5em 0 0;
+  padding: 0;
+}
+
+label#securityLevel-customWarning {
+  border-radius: 2px;
+  background-color: #ffe845;
+  text-transform: uppercase;
+  font-weight: bolder;
+  font-size: 0.8em;
+  height: 1em;
+  line-height: 1em;
+  vertical-align: middle;
+  margin: auto;
+  padding: 0.4em;
+}
+
+panelview#securityLevel-panelview description {
+  margin: 0 -0.5em 0.5em 0;
+  padding: 0 !important;
+}
+
+label#securityLevel-learnMore {
+  margin: 0 0 1.0em 0;
+  padding: 0;
+}
+
+panelview#securityLevel-panelview button {
+  -moz-appearance: none;
+  background-color: var(--arrowpanel-dimmed);
+}
+
+panelview#securityLevel-panelview button:hover {
+  background-color: var(--arrowpanel-dimmed-further);
+}
+
+panelview#securityLevel-panelview button:active {
+  background-color: var(--arrowpanel-dimmed-even-further);
+}
+
+button#securityLevel-restoreDefaults {
+  margin: 0 0 1.0em 0;
+  padding: 0.45em;
+  color: inherit !important;
+}
+
+button#securityLevel-advancedSecuritySettings {
+  margin: 0 -1.0em -1.0em -1.0em;
+  border-radius: 0;
+  border-top: 1px solid var(--panel-separator-color);
+  padding: 0;
+  height: 3.0em;
+  color: inherit !important;
+}
diff --git a/browser/components/securitylevel/content/securityLevelPanel.inc.xhtml b/browser/components/securitylevel/content/securityLevelPanel.inc.xhtml
new file mode 100644
index 000000000000..4abbb12dd856
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelPanel.inc.xhtml
@@ -0,0 +1,38 @@
+<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 class="panel-subview-body">
+        <label id="securityLevel-header"/>
+        <hbox id="securityLevel-levelHbox">
+          <label id="securityLevel-level"/>
+          <vbox>
+            <spacer flex="1"/>
+              <label id="securityLevel-customWarning"/>
+            <spacer flex="1"/>
+          </vbox>
+        </hbox>
+        <description id="securityLevel-summary"/>
+        <label
+          id="securityLevel-learnMore"
+          class="learnMore text-link"
+          onclick="SecurityLevelPanel.hide();"
+          is="text-link"/>
+        <button
+          id="securityLevel-restoreDefaults"
+          oncommand="SecurityLevelPanel.restoreDefaults();"/>
+        <button
+          id="securityLevel-advancedSecuritySettings"
+          oncommand="SecurityLevelPanel.openAdvancedSecuritySettings();"/>
+      </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..0d1040d177d8
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelPreferences.css
@@ -0,0 +1,26 @@
+label#securityLevel-customWarning {
+  border-radius: 2px;
+  background-color: #ffe845;
+  text-transform: uppercase;
+  font-weight: bolder;
+  font-size: 0.7em;
+  height: 1em;
+  line-height: 1em;
+  padding: 0.35em;
+}
+
+radiogroup#securityLevel-radiogroup radio {
+  font-weight: bold;
+}
+
+vbox#securityLevel-vbox-standard,
+vbox#securityLevel-vbox-safer,
+vbox#securityLevel-vbox-safest {
+  margin-top: 0.4em;
+}
+
+vbox#securityLevel-vbox-standard description.indent,
+vbox#securityLevel-vbox-safer description.indent,
+vbox#securityLevel-vbox-safest description.indent {
+  margin-inline-start: 0 !important;
+}
diff --git a/browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml b/browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml
new file mode 100644
index 000000000000..a108d44a7b51
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml
@@ -0,0 +1,62 @@
+<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>
+        </hbox>
+        <description flex="1">
+          <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">
+          <html:span id="securityLevel-summary" class="tail-with-learn-more"/>
+          <label id="securityLevel-restoreDefaults"
+                 class="learnMore text-link"/>
+        </description>
+        <description id="securityLevel-description1" class="indent tip-caption"/>
+        <description id="securityLevel-description2" class="indent tip-caption"/>
+        <description id="securityLevel-description3" class="indent tip-caption"/>
+      </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">
+          <html:span id="securityLevel-summary" class="tail-with-learn-more"/>
+          <label id="securityLevel-restoreDefaults"
+                 class="learnMore text-link"/>
+        </description>
+        <description id="securityLevel-description1" class="indent tip-caption"/>
+        <description id="securityLevel-description2" class="indent tip-caption"/>
+        <description id="securityLevel-description3" class="indent tip-caption"/>
+      </vbox>
+    </radiogroup>
+  </vbox>
+</groupbox>
diff --git a/browser/components/securitylevel/jar.mn b/browser/components/securitylevel/jar.mn
new file mode 100644
index 000000000000..9ac408083fbc
--- /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/securityLevelButton.svg      (content/securityLevelButton.svg)
diff --git a/browser/components/securitylevel/moz.build b/browser/components/securitylevel/moz.build
new file mode 100644
index 000000000000..7e103239c8d6
--- /dev/null
+++ b/browser/components/securitylevel/moz.build
@@ -0,0 +1 @@
+JAR_MANIFESTS += ['jar.mn']





More information about the tor-commits mailing list