Commit e59f6df8 authored by Arthur Edelstein's avatar Arthur Edelstein Committed by Georg Koppen
Browse files

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.
parent 269031f7
// 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);
};
......@@ -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>
......@@ -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() {