commit c5782ca107af15534f74ec77db43808d633b57fa Author: Richard Pospesel richard@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 7a41603d4d3f..b121ee301ee7 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -224,6 +224,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", @@ -1769,6 +1774,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 @@ -2484,6 +2492,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 bb1c53db9757..3e0c0c8dc74c 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@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);