[tor-commits] [torbutton/master] Bug 20347: Remove "Custom" checkbox; show "Restore defaults" button
gk at torproject.org
gk at torproject.org
Mon Nov 7 09:36:54 UTC 2016
commit e59f6df84dcfde500f41eefb608dd878a7fc9d6b
Author: Arthur Edelstein <arthuredelstein at gmail.com>
Date: Mon Oct 17 17:25:59 2016 -0700
Bug 20347: Remove "Custom" checkbox; show "Restore defaults" button
This patch moves the security slider code from torbutton.js
to its own file (security-prefs.js) and refactors it.
---
src/chrome/content/preferences.js | 149 ++++++------------
src/chrome/content/preferences.xul | 53 ++++---
src/chrome/content/torbutton.js | 309 ++++---------------------------------
src/chrome/locale/en/torbutton.dtd | 5 +-
src/modules/security-prefs.js | 130 ++++++++++++++++
src/modules/utils.js | 21 ++-
6 files changed, 256 insertions(+), 411 deletions(-)
diff --git a/src/chrome/content/preferences.js b/src/chrome/content/preferences.js
index 1d85cde..7856ef1 100644
--- a/src/chrome/content/preferences.js
+++ b/src/chrome/content/preferences.js
@@ -1,105 +1,44 @@
-// Bug 1506 P1: Most of this code needs to go away. See also Bug 3100.
-
-// PREFERences dialog functions
-// torbutton_prefs_init() -- on dialog load
-// torbutton_prefs_save() -- on dialog save
-
-const Cc = Components.classes, Ci = Components.interfaces;
-
-
-function torbutton_prefs_init(doc) {
- torbutton_log(2, "called prefs_init()");
-
- var o_torprefs = torbutton_get_prefbranch('extensions.torbutton.');
-
- let sec_slider = doc.getElementById('torbutton_sec_slider');
- let sec_custom = doc.getElementById('torbutton_sec_custom');
- let custom_values = o_torprefs.getBoolPref('security_custom');
- sec_slider.value = o_torprefs.getIntPref('security_slider');
- sec_custom.checked = custom_values;
- sec_custom.disabled = !custom_values;
- torbutton_set_slider_text(doc, sec_custom.checked);
- // If the custom checkbox is checked and the user is done with dragging
- // uncheck the checkbox to allow setting the (newly) chosen security level.
- sec_slider.dragStateChanged = function(isDragging) {
- if (!isDragging && sec_custom.checked) {
- sec_custom.checked = false;
- sec_custom.disabled = true;
- }
- }
- sec_slider.valueChanged = function(which, newValue, userChanged) {
- torbutton_set_slider_text(doc, false);
- }
-}
-
-function torbutton_prefs_save(doc) {
- // Disable the Accept button once the user clicked on it as clicking on
- // our active Accept button more than once can lead to all sort of weird
- // behavior. See bug 11763 for an example.
- doc.documentElement.getButton("accept").disabled = true;
- torbutton_log(2, "called prefs_save()");
- var o_torprefs = torbutton_get_prefbranch('extensions.torbutton.');
-
- o_torprefs.setBoolPref('security_custom',
- doc.getElementById('torbutton_sec_custom').checked);
- o_torprefs.setIntPref('security_slider',
- doc.getElementById('torbutton_sec_slider').value);
-
- // If we have non-custom Security Slider settings update them now.
- if (!o_torprefs.getBoolPref('security_custom')) {
- let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Components.interfaces.nsIWindowMediator);
- let win = wm.getMostRecentWindow("navigator:browser");
- win.torbutton_update_security_slider();
- }
-}
-
-function torbutton_toggle_slider(doc, pos) {
- doc.getElementById("torbutton_sec_slider").value = pos;
- // Make sure the custom checkbox is unchecked as the user seems to want one
- // of the defined security levels.
- let sec_custom = doc.getElementById("torbutton_sec_custom");
- if (sec_custom.checked) {
- sec_custom.checked = false;
- }
- torbutton_set_slider_text(doc, false);
-}
-
-function torbutton_set_slider_text(doc, custom) {
- let level = doc.getElementById("torbutton_sec_slider").value;
- if (custom) {
- level = 5;
- }
- switch (level) {
- case (1):
- doc.getElementById("desc_low").collapsed = true;
- doc.getElementById("desc_medium_low").collapsed = true;
- doc.getElementById("desc_medium_high").collapsed = true;
- doc.getElementById("desc_high").collapsed = false;
- break;
- case (2):
- doc.getElementById("desc_low").collapsed = true;
- doc.getElementById("desc_medium_low").collapsed = true;
- doc.getElementById("desc_medium_high").collapsed = false;
- doc.getElementById("desc_high").collapsed = true;
- break;
- case (3):
- doc.getElementById("desc_low").collapsed = true;
- doc.getElementById("desc_medium_low").collapsed = false;
- doc.getElementById("desc_medium_high").collapsed = true;
- doc.getElementById("desc_high").collapsed = true;
- break;
- case (4):
- doc.getElementById("desc_low").collapsed = false;
- doc.getElementById("desc_medium_low").collapsed = true;
- doc.getElementById("desc_medium_high").collapsed = true;
- doc.getElementById("desc_high").collapsed = true;
- break;
- case (5):
- doc.getElementById("desc_low").collapsed = true;
- doc.getElementById("desc_medium_low").collapsed = true;
- doc.getElementById("desc_medium_high").collapsed = true;
- doc.getElementById("desc_high").collapsed = true;
- break;
- }
-}
+// # Security Settings User Interface
+
+// Utilities
+let { utils: Cu } = Components;
+let { getBoolPref, getIntPref, setBoolPref, setIntPref } =
+ Cu.import("resource://gre/modules/Services.jsm").Services.prefs;
+
+// Description elements have the follow names.
+const descNames =
+ [, "desc_high", "desc_medium_high", "desc_medium_low", "desc_low"];
+
+// A single `state` object that reflects the user settings in this UI.
+let state = { slider : 0, custom : false};
+
+// Set the desired slider value and update UI.
+function torbutton_set_slider(sliderPosition) {
+ state.slider = sliderPosition;
+ let slider = document.getElementById("torbutton_sec_slider");
+ slider.value = sliderPosition;
+ let descs = descNames.map(name => document.getElementById(name));
+ descs.forEach((desc, i) => desc.collapsed = sliderPosition !== i);
+};
+
+// Set the desired custom value and update UI.
+function torbutton_set_custom(customValue) {
+ state.custom = customValue;
+ let sliderSettings = document.getElementById("torbutton_slider_settings");
+ let customSettings = document.getElementById("torbutton_custom_settings");
+ sliderSettings.hidden = customValue;
+ customSettings.hidden = !customValue;
+};
+
+// Read prefs 'extensions.torbutton.security_slider' and
+// 'extensions.torbutton.security_custom', and initialize the UI.
+function torbutton_init_security_ui() {
+ torbutton_set_slider(getIntPref("extensions.torbutton.security_slider"));
+ torbutton_set_custom(getBoolPref("extensions.torbutton.security_custom"));
+};
+
+// Write the two prefs from the current settings.
+function torbutton_save_security_settings() {
+ setIntPref("extensions.torbutton.security_slider", state.slider);
+ setBoolPref("extensions.torbutton.security_custom", state.custom);
+};
diff --git a/src/chrome/content/preferences.xul b/src/chrome/content/preferences.xul
index 574932e..53abd7f 100644
--- a/src/chrome/content/preferences.xul
+++ b/src/chrome/content/preferences.xul
@@ -10,64 +10,59 @@
title="&torbutton.prefs.security_settings;"
buttons="accept,cancel"
persist="screenX screenY width height"
- onload="torbutton_prefs_init(document)"
+ onload="torbutton_init_security_ui()"
align="stretch"
pack="center"
- maxheight="350"
+ maxheight="300"
+ minwidth="300"
maxwidth="400"
- ondialogaccept="torbutton_prefs_save(document)" >
+ ondialogaccept="torbutton_save_security_settings()"
+ width="400" >
<script type="application/x-javascript" src="torbutton_util.js"/>
<script type="application/x-javascript" src="preferences.js"/>
<vbox flex="1" align="stretch">
<groupbox align="stretch" flex="1"> <!-- security settings container -->
<caption label="&torbutton.prefs.sec_caption;"/>
- <hbox flex="1" align="stretch">
+ <hbox id="torbutton_slider_settings" flex="1" align="stretch" hidden="false">
<vbox>
<hbox height="200">
<vbox>
<scale id="torbutton_sec_slider" flex="1" min="1" max="4"
- movetoclick="true" orient="vertical"/>
+ movetoclick="true" orient="vertical"
+ onchange="torbutton_set_slider(this.value)"/>
</vbox>
<vbox>
<hbox flex="1" align="start">
<description id="torbutton_sec_high"
- tooltip="high_preview"
- onclick="torbutton_toggle_slider(document, 1);">
+ onclick="torbutton_set_slider(1);"
+ tooltip="high_preview">
&torbutton.prefs.sec_high;
</description>
</hbox>
<hbox flex="1" align="center">
<description id="torbutton_sec_med_high"
- tooltip="mh_preview"
- onclick="torbutton_toggle_slider(document, 2);">
+ onclick="torbutton_set_slider(2);"
+ tooltip="mh_preview">
&torbutton.prefs.sec_med_high;
</description>
</hbox>
<hbox flex="1" align="center">
<description id="torbutton_sec_med_low"
- tooltip="ml_preview"
- onclick="torbutton_toggle_slider(document, 3);">
+ onclick="torbutton_set_slider(3);"
+ tooltip="ml_preview">
&torbutton.prefs.sec_med_low;
</description>
</hbox>
<hbox flex="1" align="end">
<description id="torbutton_sec_low"
- tooltip="low_preview"
- onclick="torbutton_toggle_slider(document, 4);">
+ onclick="torbutton_set_slider(4);"
+ tooltip="low_preview">
&torbutton.prefs.sec_low;
</description>
</hbox>
</vbox>
</hbox>
- <hbox>
- <!-- We are using |oncommand| instead of |onclick| as the former does
- not fire if the checkbox is disabled and it does fire after the
- checkbox adapted its state. -->
- <checkbox id="torbutton_sec_custom" flex="1"
- oncommand="torbutton_set_slider_text(document, event.target.checked);"
- label="&torbutton.prefs.sec_custom;"/>
- </hbox>
</vbox>
<!-- A width of 400 is already too much for OS X it seems. The above
spacer tag would basically be useless and the layout ugly. -->
@@ -161,6 +156,20 @@
</vbox>
</vbox>
</hbox>
+ <vbox id="torbutton_custom_settings"
+ hidden="true"
+ width="300"
+ height="200"
+ style="overflow:auto;">
+ <description>
+ &torbutton.prefs.custom_warning;
+ </description>
+ <hbox>
+ <button id="torbutton_restore_defaults_button"
+ oncommand="torbutton_set_custom(false);"
+ label="&torbutton.prefs.restore_defaults;"/>
+ </hbox>
+ </vbox>
</groupbox>
</vbox>
@@ -200,4 +209,4 @@
<html:br></html:br>
<html:div>&torbutton.prefs.sec_low_usable_desc;</html:div>
</tooltip>
-</dialog>
+ </dialog>
diff --git a/src/chrome/content/torbutton.js b/src/chrome/content/torbutton.js
index 9a8b9e2..60f12d6 100644
--- a/src/chrome/content/torbutton.js
+++ b/src/chrome/content/torbutton.js
@@ -11,6 +11,7 @@ let { LoadContextInfo } = Cu.import('resource://gre/modules/LoadContextInfo.jsm'
let { Services } = Cu.import("resource://gre/modules/Services.jsm");
let { showDialog } = Cu.import("resource://torbutton/modules/utils.js");
let { unescapeTorString } = Cu.import("resource://torbutton/modules/utils.js");
+let SecurityPrefs = Cu.import("resource://torbutton/modules/security-prefs.js");
const k_tb_last_browser_version_pref = "extensions.torbutton.lastBrowserVersion";
const k_tb_browser_update_needed_pref = "extensions.torbutton.updateNeeded";
@@ -45,8 +46,6 @@ var m_tb_orig_BrowserOnAboutPageLoad = null;
var m_tb_domWindowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
-var m_tb_sliderUpdate = false;
-
// Bug 1506 P1: This object is only for updating the UI for toggling and style
var torbutton_window_pref_observer =
{
@@ -86,11 +85,7 @@ var torbutton_unique_pref_observer =
m_tb_prefs.addObserver("network.cookie", this, false);
m_tb_prefs.addObserver("browser.privatebrowsing.autostart", this, false);
m_tb_prefs.addObserver("javascript", this, false);
- m_tb_prefs.addObserver("gfx", this, false);
m_tb_prefs.addObserver("noscript", this, false);
- m_tb_prefs.addObserver("media", this, false);
- m_tb_prefs.addObserver("mathml", this, false);
- m_tb_prefs.addObserver("svg", this, false);
m_tb_prefs.addObserver("plugin.disable", this, false);
m_tb_prefs.addObserver("privacy.thirdparty.isolate", this, false);
m_tb_prefs.addObserver("privacy.resistFingerprinting", this, false);
@@ -107,11 +102,10 @@ var torbutton_unique_pref_observer =
m_tb_prefs.removeObserver("network.cookie", this);
m_tb_prefs.removeObserver("browser.privatebrowsing.autostart", this);
m_tb_prefs.removeObserver("javascript", this);
- m_tb_prefs.removeObserver("gfx", this);
m_tb_prefs.removeObserver("noscript", this);
- m_tb_prefs.removeObserver("media", this);
- m_tb_prefs.removeObserver("mathml", this);
- m_tb_prefs.removeObserver("svg", this);
+ m_tb_prefs.removeObserver("plugin.disable", this);
+ m_tb_prefs.removeObserver("privacy.thirdparty.isolate", this);
+ m_tb_prefs.removeObserver("privacy.resistFingerprinting", this);
var observerService = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
@@ -149,7 +143,9 @@ var torbutton_unique_pref_observer =
}
if (topic != "nsPref:changed") return;
-
+ if (data.startsWith("noscript.")) {
+ torbutton_update_noscript_button();
+ }
switch (data) {
case "network.cookie.cookieBehavior":
var val = m_tb_prefs.getIntPref("network.cookie.cookieBehavior");
@@ -180,42 +176,6 @@ var torbutton_unique_pref_observer =
case "extensions.torbutton.hide_sync_ui":
torbutton_update_sync_ui();
break;
- case "gfx.font_rendering.opentype_svg.enabled":
- case "javascript.options.ion.content":
- case "javascript.options.typeinference":
- case "noscript.forbidMedia":
- case "media.webaudio.enabled":
- case "mathml.disabled":
- case "javascript.options.baselinejit.content":
- case "noscript.forbidFonts":
- case "noscript.globalHttpsWhitelist":
- case "noscript.global":
- case "svg.in-content.enabled":
- // |m_tb_slider_update| is only set if the user updated a
- // preference under control of the security slider via the
- // slider on the Torbutton dialog. This in turn means we can
- // skip the code dealing with setting/unsetting the custom mode
- // in this case.
- if (!m_tb_sliderUpdate) {
- // Do we already have custom settings?
- let customSlider = m_tb_prefs.
- getBoolPref("extensions.torbutton.security_custom");
- // A preference governed by the security slider got changed
- // but we are not in custom mode yet. Change that.
- if (!customSlider) {
- m_tb_prefs.
- setBoolPref("extensions.torbutton.security_custom",
- true);
- } else {
- // We are in custom mode. Check whether all prefs are
- // reset and reset the mode if so. Otherwise we remain
- // in custom mode.
- torbutton_log(4, "custom mode and we got: " + data);
- torbutton_security_slider_custom_check(m_tb_prefs.
- getIntPref("extensions.torbutton.security_slider"));
- }
- }
- break;
}
}
}
@@ -269,7 +229,9 @@ function torbutton_init_toolbutton()
// called once per browser window.. This might belong in a component.
function torbutton_init() {
torbutton_log(3, 'called init()');
-
+
+ SecurityPrefs.initialize();
+
if (m_tb_wasinited) {
return;
}
@@ -372,12 +334,6 @@ function torbutton_init() {
torbutton_on_abouttor_load(aEvent.target);
}, false, true);
- // Set some important security prefs according to the chosen security level
- // if there are no custom settings to respect.
- if (!m_tb_prefs.getBoolPref("extensions.torbutton.security_custom")) {
- torbutton_update_security_slider();
- }
-
// XXX: Get rid of the cached asmjs (or IndexedDB) files on disk in case we
// don't allow things saved to disk. This is an ad-hoc fix to work around
// #19417. Once this is properly solved we should remove this code again.
@@ -1805,228 +1761,6 @@ function torbutton_update_thirdparty_prefs() {
m_tb_prefs.savePrefFile(null);
}
-var torbutton_sec_ml_bool_prefs = {
- "javascript.options.ion.content" : false,
- "javascript.options.typeinference" : false,
- "noscript.forbidMedia" : true,
- "media.webaudio.enabled" : false,
- "mathml.disabled" : true
-};
-
-var torbutton_sec_mh_bool_prefs = {
- "javascript.options.baselinejit.content" : false,
- "gfx.font_rendering.opentype_svg.enabled" : false,
- "noscript.global" : false,
- "noscript.globalHttpsWhitelist" : true
-};
-
-var torbutton_sec_h_bool_prefs = {
- "noscript.forbidFonts" : true,
- "noscript.global" : false,
- "svg.in-content.enabled" : false
-};
-
-function torbutton_update_security_slider() {
- // Avoid checking the custom settings checkbox.
- m_tb_sliderUpdate = true;
- let mode = m_tb_prefs.getIntPref("extensions.torbutton.security_slider");
- let capValue = m_tb_prefs.getCharPref("capability.policy.maonoscript.sites");
- switch (mode) {
- case 1:
- for (p in torbutton_sec_ml_bool_prefs) {
- m_tb_prefs.setBoolPref(p, torbutton_sec_ml_bool_prefs[p])
- }
- for (p in torbutton_sec_mh_bool_prefs) {
- m_tb_prefs.setBoolPref(p, torbutton_sec_mh_bool_prefs[p])
- // noscript.globalHttpsWhitelist is special: We don't want it in this
- // mode.
- if (p === "noscript.globalHttpsWhitelist") {
- m_tb_prefs.setBoolPref(p, !torbutton_sec_mh_bool_prefs[p])
- }
- }
- for (p in torbutton_sec_h_bool_prefs) {
- m_tb_prefs.setBoolPref(p, torbutton_sec_h_bool_prefs[p])
- }
- // Removing "https:" is needed due to a bug in older Noscript versions.
- // We leave that in for a while as there may be users that were affected
- // by this bug. Removing it immediately and having the auto-updater might
- // leave users exposed to the problem.
- if (capValue.indexOf(" https:") >= 0) {
- m_tb_prefs.setCharPref("capability.policy.maonoscript.sites",
- capValue.replace(" https:", ""));
- }
- break;
- case 2:
- for (p in torbutton_sec_ml_bool_prefs) {
- m_tb_prefs.setBoolPref(p, torbutton_sec_ml_bool_prefs[p])
- }
- // Order matters here as both the high mode and the medium-high mode
- // share some preferences/values. So, let's revert the high mode
- // preferences first and set the medium-high mode ones afterwards.
- for (p in torbutton_sec_h_bool_prefs) {
- m_tb_prefs.setBoolPref(p, !torbutton_sec_h_bool_prefs[p])
- }
- for (p in torbutton_sec_mh_bool_prefs) {
- m_tb_prefs.setBoolPref(p, torbutton_sec_mh_bool_prefs[p])
- }
- break;
- case 3:
- for (p in torbutton_sec_ml_bool_prefs) {
- m_tb_prefs.setBoolPref(p, torbutton_sec_ml_bool_prefs[p])
- }
- for (p in torbutton_sec_mh_bool_prefs) {
- m_tb_prefs.setBoolPref(p, !torbutton_sec_mh_bool_prefs[p])
- }
- for (p in torbutton_sec_h_bool_prefs) {
- m_tb_prefs.setBoolPref(p, !torbutton_sec_h_bool_prefs[p])
- }
- // Removing "https:" is needed due to a bug in older Noscript versions.
- // We leave that in for a while as there may be users that were affected
- // by this bug. Removing it immediately and having the auto-updater might
- // leave users exposed to the problem.
- if (capValue.indexOf(" https:") >= 0) {
- m_tb_prefs.setCharPref("capability.policy.maonoscript.sites",
- capValue.replace(" https:", ""));
- }
- break;
- case 4:
- for (p in torbutton_sec_ml_bool_prefs) {
- m_tb_prefs.setBoolPref(p, !torbutton_sec_ml_bool_prefs[p])
- }
- for (p in torbutton_sec_mh_bool_prefs) {
- m_tb_prefs.setBoolPref(p, !torbutton_sec_mh_bool_prefs[p])
- }
- for (p in torbutton_sec_h_bool_prefs) {
- m_tb_prefs.setBoolPref(p, !torbutton_sec_h_bool_prefs[p])
- }
- // Removing "https:" is needed due to a bug in older Noscript versions.
- // We leave that in for a while as there may be users that were affected
- // by this bug. Removing it immediately and having the auto-updater might
- // leave users exposed to the problem.
- if (capValue.indexOf(" https:") >= 0) {
- m_tb_prefs.setCharPref("capability.policy.maonoscript.sites",
- capValue.replace(" https:", ""));
- }
- break;
- }
- /* Update the NoScript button to reflect any changes */
- try {
- let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Components.interfaces.nsIWindowMediator);
- let browserEnumerator = wm.getEnumerator("navigator:browser");
-
- // Update every window's NoScript status...
- while (browserEnumerator.hasMoreElements()) {
- let win = browserEnumerator.getNext();
- win.noscriptOverlay._syncUINow();
- }
- torbutton_log(3, 'Updated NoScript status for security slider');
- } catch(e) {
- torbutton_log(4, 'Failed to update NoScript status for security slider: '+e);
- }
- torbutton_log(3, 'Security Slider Pref Update Complete');
- m_tb_sliderUpdate = false;
-}
-
-// The user (re)set a pref which is relevant to the security slider while she
-// was in custom mode. Check whether the preference values fit to the mode which
-// is still on the slider. Iff so, we are leaving the custom mode.
-function torbutton_security_slider_custom_check(mode) {
- let capValue = m_tb_prefs.getCharPref("capability.policy.maonoscript.sites");
- switch (mode) {
- case 1:
- for (p in torbutton_sec_ml_bool_prefs) {
- if (m_tb_prefs.getBoolPref(p) !== torbutton_sec_ml_bool_prefs[p]) {
- return;
- }
- }
- for (p in torbutton_sec_mh_bool_prefs) {
- if (m_tb_prefs.getBoolPref(p) !== torbutton_sec_mh_bool_prefs[p]) {
- // We don't want to have the whitelist in high mode. JavaScript is
- // disabled globally.
- if (p === "noscript.globalHttpsWhitelist") {
- continue;
- }
- return;
- }
- }
- for (p in torbutton_sec_h_bool_prefs) {
- if (m_tb_prefs.getBoolPref(p) !== torbutton_sec_h_bool_prefs[p]) {
- return;
- }
- }
- // We are still here which means all preferences are properly reset. Leave
- // custom mode.
- m_tb_prefs.setBoolPref("extensions.torbutton.security_custom", false);
- break;
- case 2:
- for (p in torbutton_sec_ml_bool_prefs) {
- if (m_tb_prefs.getBoolPref(p) !== torbutton_sec_ml_bool_prefs[p]) {
- return;
- }
- }
- for (p in torbutton_sec_mh_bool_prefs) {
- if (m_tb_prefs.getBoolPref(p) !== torbutton_sec_mh_bool_prefs[p]) {
- return;
- }
- }
- for (p in torbutton_sec_h_bool_prefs) {
- if (m_tb_prefs.getBoolPref(p) === torbutton_sec_h_bool_prefs[p]) {
- // We have the whitelist and JavaScript is disabled in medium-high
- // mode as well.
- if (p === "noscript.global") {
- continue;
- }
- return;
- }
- }
- // We are still here which means all preferences are properly reset. Leave
- // custom mode.
- m_tb_prefs.setBoolPref("extensions.torbutton.security_custom", false);
- break;
- case 3:
- for (p in torbutton_sec_ml_bool_prefs) {
- if (m_tb_prefs.getBoolPref(p) !== torbutton_sec_ml_bool_prefs[p]) {
- return;
- }
- }
- for (p in torbutton_sec_mh_bool_prefs) {
- if (m_tb_prefs.getBoolPref(p) === torbutton_sec_mh_bool_prefs[p]) {
- return;
- }
- }
- for (p in torbutton_sec_h_bool_prefs) {
- if (m_tb_prefs.getBoolPref(p) === torbutton_sec_h_bool_prefs[p]) {
- return;
- }
- }
- // We are still here which means all preferences are properly reset. Leave
- // custom mode.
- m_tb_prefs.setBoolPref("extensions.torbutton.security_custom", false);
- break;
- case 4:
- for (p in torbutton_sec_ml_bool_prefs) {
- if (m_tb_prefs.getBoolPref(p) === torbutton_sec_ml_bool_prefs[p]) {
- return;
- }
- }
- for (p in torbutton_sec_mh_bool_prefs) {
- if (m_tb_prefs.getBoolPref(p) === torbutton_sec_mh_bool_prefs[p]) {
- return;
- }
- }
- for (p in torbutton_sec_h_bool_prefs) {
- if (m_tb_prefs.getBoolPref(p) === torbutton_sec_h_bool_prefs[p]) {
- return;
- }
- }
- // We are still here which means all preferences are properly reset. Leave
- // custom mode.
- m_tb_prefs.setBoolPref("extensions.torbutton.security_custom", false);
- break;
- }
-}
-
function torbutton_close_tabs_on_new_identity() {
var close_newnym = m_tb_prefs.getBoolPref("extensions.torbutton.close_newnym");
if (!close_newnym) {
@@ -2829,4 +2563,27 @@ function torbutton_update_sync_ui()
}
}
+// Update the NoScript button to reflect any changes to noscript prefs
+function torbutton_update_noscript_button()
+{
+ // Make sure pref values have fully propagated inside NoScript before
+ // we sync the UI.
+ setTimeout(() => {
+ try {
+ let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Components.interfaces.nsIWindowMediator);
+ let browserEnumerator = wm.getEnumerator("navigator:browser");
+ // Update every window's NoScript status...
+ while (browserEnumerator.hasMoreElements()) {
+ let win = browserEnumerator.getNext();
+ win.noscriptOverlay._syncUINow();
+ }
+ torbutton_log(3, 'Updated NoScript status for security settings');
+ } catch (e) {
+ torbutton_log(4, 'Failed to update NoScript status for security setings: '+e);
+ }
+ }, 0);
+}
+
+
//vim:set ts=4
diff --git a/src/chrome/locale/en/torbutton.dtd b/src/chrome/locale/en/torbutton.dtd
index 56f663e..0c10406 100644
--- a/src/chrome/locale/en/torbutton.dtd
+++ b/src/chrome/locale/en/torbutton.dtd
@@ -11,7 +11,9 @@
<!ENTITY torbutton.context_menu.cookieProtections "Cookie Protections…">
<!ENTITY torbutton.context_menu.cookieProtections.key "C">
<!ENTITY torbutton.button.tooltip "Click to initialize Torbutton">
-<!ENTITY torbutton.prefs.security_settings "Security Settings">
+<!ENTITY torbutton.prefs.security_settings "Tor Browser Security Settings">
+<!ENTITY torbutton.prefs.restore_defaults "Restore Defaults">
+<!ENTITY torbutton.prefs.custom_warning "Your custom browser preferences have resulted in unusual security settings. For security and privacy reasons, we recommend you choose one of the default security levels.">
<!ENTITY torbutton.cookiedialog.title "Manage Cookie Protections">
<!ENTITY torbutton.cookiedialog.lockCol "Protected">
<!ENTITY torbutton.cookiedialog.domainCol "Host">
@@ -57,5 +59,4 @@
<!ENTITY torbutton.prefs.sec_all_js_desc "JavaScript is disabled by default on all sites.">
<!ENTITY torbutton.prefs.sec_webfonts_desc "Some fonts and icons may display incorrectly.">
<!ENTITY torbutton.prefs.sec_webfonts_desc_tooltip "Website-provided font files are blocked.">
-<!ENTITY torbutton.prefs.sec_custom "Custom Values">
<!ENTITY torbutton.circuit_display.title "Tor circuit for this site">
diff --git a/src/modules/security-prefs.js b/src/modules/security-prefs.js
new file mode 100644
index 0000000..3710862
--- /dev/null
+++ b/src/modules/security-prefs.js
@@ -0,0 +1,130 @@
+// # Security Settings prefs (as controlled by the Security Slider)
+
+// ### Utilities
+
+let {classes: Cc, utils: Cu } = Components;
+let { getBoolPref, setBoolPref, getIntPref, setIntPref } =
+ Cu.import("resource://gre/modules/Services.jsm").Services.prefs;
+let { bindPref } =
+ Cu.import("resource://torbutton/modules/utils.js");
+let logger = Components.classes["@torproject.org/torbutton-logger;1"]
+ .getService(Components.interfaces.nsISupports).wrappedJSObject;
+let log = (level, msg) => logger.log(level, msg);
+
+// ### Constants
+
+// __kSecuritySettings__.
+// A table of all prefs bound to the security slider, and the value
+// for each security setting.
+const kSecuritySettings = {
+ // Preference name : [0, 1-high 2-mh 3-ml 4-low]
+ "javascript.options.ion.content" : [, false, false, false, true ],
+ "javascript.options.typeinference" : [, false, false, false, true ],
+ "noscript.forbidMedia" : [, true, true, true, false],
+ "media.webaudio.enabled" : [, false, false, false, true ],
+ "mathml.disabled" : [, true, true, true, false],
+ "javascript.options.baselinejit.content" : [, false, false, true, true ],
+ "gfx.font_rendering.opentype_svg.enabled" : [, false, false, true, true ],
+ "noscript.global" : [, false, false, true, true ],
+ "noscript.globalHttpsWhitelist" : [, false, true, false, false],
+ "noscript.forbidFonts" : [, true, false, false, false],
+ "svg.in-content.enabled" : [, false, true, true, true ],
+};
+
+// The Security Settings prefs in question.
+const kSliderPref = "extensions.torbutton.security_slider";
+const kCustomPref = "extensions.torbutton.security_custom";
+
+// ### Prefs
+
+// __write_setting_to_prefs(settingIndex)__.
+// Take a given setting index and write the appropriate pref values
+// to the pref database.
+var write_setting_to_prefs = function (settingIndex) {
+ Object.keys(kSecuritySettings).forEach(
+ prefName => setBoolPref(
+ prefName, kSecuritySettings[prefName][settingIndex]));
+};
+
+// __read_setting_from_prefs()__.
+// Read the current pref values, and decide if any of our
+// security settings matches. Otherwise return null.
+var read_setting_from_prefs = function () {
+ let prefNames = Object.keys(kSecuritySettings);
+ for (let settingIndex of [1, 2, 3, 4]) {
+ let possibleSetting = true;
+ // For the given settingIndex, check if all current pref values
+ // match the setting.
+ for (let prefName of prefNames) {
+ if (kSecuritySettings[prefName][settingIndex] !==
+ getBoolPref(prefName)) {
+ possibleSetting = false;
+ }
+ }
+ if (possibleSetting) {
+ // We have a match!
+ return settingIndex;
+ }
+ }
+ // No matching setting; return null.
+ return null;
+};
+
+// __watch_security_prefs(onSettingChanged)__.
+// Whenever a pref bound to the security slider changes, onSettingChanged
+// is called with the new security setting value (1,2,3,4 or null).
+// Returns a zero-arg function that ends this binding.
+var watch_security_prefs = function (onSettingChanged) {
+ let prefNames = Object.keys(kSecuritySettings);
+ let unbindFuncs = [];
+ for (let prefName of prefNames) {
+ unbindFuncs.push(bindPref(
+ prefName, () => onSettingChanged(read_setting_from_prefs())));
+ }
+ // Call all the unbind functions.
+ return () => unbindFuncs.forEach(unbind => unbind());
+};
+
+// __initialized__.
+// Have we called initialize() yet?
+var initialized = false;
+
+// __initialize()__.
+// Defines the behavior of "extensions.torbutton.security_custom",
+// "extensions.torbutton.security_slider", and the security-sensitive
+// prefs declared in kSecuritySettings.
+var initialize = function () {
+ // Only run once.
+ if (initialized) {
+ return;
+ }
+ log(4, "Initializing security-prefs.js");
+ initialized = true;
+ // When security_custom is set to false, apply security_slider setting
+ // to the security-sensitive prefs.
+ bindPref(kCustomPref, function (custom) {
+ if (custom === false) {
+ write_setting_to_prefs(getIntPref(kSliderPref));
+ }
+ });
+ // If security_slider is given a new value, then security_custom should
+ // be set to false.
+ bindPref(kSliderPref, function (prefIndex) {
+ setBoolPref(kCustomPref, false);
+ write_setting_to_prefs(prefIndex);
+ });
+ // If a security-sensitive pref changes, then decide if the set of pref values
+ // constitutes a security_slider setting or a custom value.
+ watch_security_prefs(settingIndex => {
+ if (settingIndex === null) {
+ setBoolPref(kCustomPref, true);
+ } else {
+ setIntPref(kSliderPref, settingIndex);
+ setBoolPref(kCustomPref, false);
+ }
+ });
+ log(4, "security-prefs.js initialization complete");
+};
+
+// Export initialize() function for external use.
+let EXPORTED_SYMBOLS = ["initialize"];
diff --git a/src/modules/utils.js b/src/modules/utils.js
index b303485..507f008 100644
--- a/src/modules/utils.js
+++ b/src/modules/utils.js
@@ -23,11 +23,11 @@ var getPrefValue = function (prefName) {
}
};
-// __bindPrefAndInit(prefName, prefHandler)__
-// Applies prefHandler to the current value of pref specified by prefName.
-// Re-applies prefHandler whenever the value of the pref changes.
+// __bindPref(prefName, prefHandler, init)__
+// Applies prefHandler whenever the value of the pref changes.
+// If init is true, applies prefHandler to the current value.
// Returns a zero-arg function that unbinds the pref.
-var bindPrefAndInit = function (prefName, prefHandler) {
+var bindPref = function (prefName, prefHandler, init = false) {
let update = () => { prefHandler(getPrefValue(prefName)); },
observer = { observe : function (subject, topic, data) {
if (data === prefName) {
@@ -35,10 +35,19 @@ var bindPrefAndInit = function (prefName, prefHandler) {
}
} };
prefs.addObserver(prefName, observer, false);
- update();
+ if (init) {
+ update();
+ }
return () => { prefs.removeObserver(prefName, observer); };
};
+// __bindPrefAndInit(prefName, prefHandler)__
+// Applies prefHandler to the current value of pref specified by prefName.
+// Re-applies prefHandler whenever the value of the pref changes.
+// Returns a zero-arg function that unbinds the pref.
+var bindPrefAndInit = (prefName, prefHandler) =>
+ bindPref(prefName, prefHandler, true);
+
// ## Environment variables
// __env__.
@@ -173,5 +182,5 @@ var unescapeTorString = function(str) {
};
// Export utility functions for external use.
-let EXPORTED_SYMBOLS = ["bindPrefAndInit", "getPrefValue", "getEnv",
+let EXPORTED_SYMBOLS = ["bindPref", "bindPrefAndInit", "getEnv", "getPrefValue",
"showDialog", "unescapeTorString"];
More information about the tor-commits
mailing list