diff options
Diffstat (limited to 'toolkit/mozapps/preferences')
-rw-r--r-- | toolkit/mozapps/preferences/changemp.js | 220 | ||||
-rw-r--r-- | toolkit/mozapps/preferences/changemp.xhtml | 96 | ||||
-rw-r--r-- | toolkit/mozapps/preferences/fontbuilder.js | 120 | ||||
-rw-r--r-- | toolkit/mozapps/preferences/jar.mn | 11 | ||||
-rw-r--r-- | toolkit/mozapps/preferences/moz.build | 10 | ||||
-rw-r--r-- | toolkit/mozapps/preferences/removemp.js | 52 | ||||
-rw-r--r-- | toolkit/mozapps/preferences/removemp.xhtml | 54 |
7 files changed, 563 insertions, 0 deletions
diff --git a/toolkit/mozapps/preferences/changemp.js b/toolkit/mozapps/preferences/changemp.js new file mode 100644 index 0000000000..2062d497df --- /dev/null +++ b/toolkit/mozapps/preferences/changemp.js @@ -0,0 +1,220 @@ +// -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1"; +const nsIPK11TokenDB = Ci.nsIPK11TokenDB; +const nsIDialogParamBlock = Ci.nsIDialogParamBlock; +const nsPKCS11ModuleDB = "@mozilla.org/security/pkcs11moduledb;1"; +const nsIPKCS11ModuleDB = Ci.nsIPKCS11ModuleDB; +const nsIPKCS11Slot = Ci.nsIPKCS11Slot; +const nsIPK11Token = Ci.nsIPK11Token; + +var params; +var pw1; + +function init() { + pw1 = document.getElementById("pw1"); + + process(); + document.addEventListener("dialogaccept", setPassword); +} + +function process() { + // If the token is unitialized, don't use the old password box. + // Otherwise, do. + + let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"].getService( + Ci.nsIPK11TokenDB + ); + let token = tokenDB.getInternalKeyToken(); + if (token) { + let oldpwbox = document.getElementById("oldpw"); + let msgBox = document.getElementById("message"); + if ((token.needsLogin() && token.needsUserInit) || !token.needsLogin()) { + oldpwbox.hidden = true; + msgBox.hidden = false; + + if (!token.needsLogin()) { + oldpwbox.setAttribute("inited", "empty"); + } else { + oldpwbox.setAttribute("inited", "true"); + } + + // Select first password field + document.getElementById("pw1").focus(); + } else { + // Select old password field + oldpwbox.hidden = false; + msgBox.hidden = true; + oldpwbox.setAttribute("inited", "false"); + oldpwbox.focus(); + } + } + + if ( + !token.hasPassword && + !Services.policies.isAllowed("removeMasterPassword") + ) { + document.getElementById("admin").hidden = false; + } + + if (params) { + // Return value 0 means "canceled" + params.SetInt(1, 0); + } + + checkPasswords(); +} + +async function createAlert(titleL10nId, messageL10nId) { + const [title, message] = await document.l10n.formatValues([ + { id: titleL10nId }, + { id: messageL10nId }, + ]); + Services.prompt.alert(window, title, message); +} + +function setPassword() { + var pk11db = Cc[nsPK11TokenDB].getService(nsIPK11TokenDB); + var token = pk11db.getInternalKeyToken(); + + var oldpwbox = document.getElementById("oldpw"); + var initpw = oldpwbox.getAttribute("inited"); + + if (initpw == "false" || initpw == "empty") { + try { + var oldpw = ""; + var passok = 0; + + if (initpw == "empty") { + passok = 1; + } else { + oldpw = oldpwbox.value; + passok = token.checkPassword(oldpw); + } + + if (passok) { + if (initpw == "empty" && pw1.value == "") { + // This makes no sense that we arrive here, + // we reached a case that should have been prevented by checkPasswords. + } else { + if (pw1.value == "") { + var secmoddb = Cc[nsPKCS11ModuleDB].getService(nsIPKCS11ModuleDB); + if (secmoddb.isFIPSEnabled) { + // empty passwords are not allowed in FIPS mode + createAlert( + "pw-change-failed-title", + "pp-change2empty-in-fips-mode" + ); + passok = 0; + } + } + if (passok) { + token.changePassword(oldpw, pw1.value); + if (pw1.value == "") { + createAlert("pw-change-success-title", "settings-pp-erased-ok"); + } else { + createAlert("pw-change-success-title", "pp-change-ok"); + } + } + } + } else { + oldpwbox.focus(); + oldpwbox.setAttribute("value", ""); + createAlert("pw-change-failed-title", "incorrect-pp"); + } + } catch (e) { + console.error(e); + createAlert("pw-change-failed-title", "failed-pp-change"); + } + } else { + token.initPassword(pw1.value); + if (pw1.value == "") { + createAlert("pw-change-success-title", "settings-pp-not-wanted"); + } + } +} + +function setPasswordStrength() { + // Here is how we weigh the quality of the password + // number of characters + // numbers + // non-alpha-numeric chars + // upper and lower case characters + + var pw = document.getElementById("pw1").value; + + // length of the password + var pwlength = pw.length; + if (pwlength > 5) { + pwlength = 5; + } + + // use of numbers in the password + var numnumeric = pw.replace(/[0-9]/g, ""); + var numeric = pw.length - numnumeric.length; + if (numeric > 3) { + numeric = 3; + } + + // use of symbols in the password + var symbols = pw.replace(/\W/g, ""); + var numsymbols = pw.length - symbols.length; + if (numsymbols > 3) { + numsymbols = 3; + } + + // use of uppercase in the password + var numupper = pw.replace(/[A-Z]/g, ""); + var upper = pw.length - numupper.length; + if (upper > 3) { + upper = 3; + } + + var pwstrength = + pwlength * 10 - 20 + numeric * 10 + numsymbols * 15 + upper * 10; + + // make sure we're give a value between 0 and 100 + if (pwstrength < 0) { + pwstrength = 0; + } + + if (pwstrength > 100) { + pwstrength = 100; + } + + var mymeter = document.getElementById("pwmeter"); + mymeter.value = pwstrength; +} + +function checkPasswords() { + var pw1 = document.getElementById("pw1").value; + var pw2 = document.getElementById("pw2").value; + var ok = document.getElementById("changemp").getButton("accept"); + + var oldpwbox = document.getElementById("oldpw"); + if (oldpwbox) { + var initpw = oldpwbox.getAttribute("inited"); + + if (initpw == "empty" && pw1 == "") { + // The token has already been initialized, therefore this dialog + // was called with the intention to change the password. + // The token currently uses an empty password. + // We will not allow changing the password from empty to empty. + ok.setAttribute("disabled", "true"); + return; + } + } + + if ( + pw1 == pw2 && + (pw1 != "" || Services.policies.isAllowed("removeMasterPassword")) + ) { + ok.setAttribute("disabled", "false"); + } else { + ok.setAttribute("disabled", "true"); + } +} diff --git a/toolkit/mozapps/preferences/changemp.xhtml b/toolkit/mozapps/preferences/changemp.xhtml new file mode 100644 index 0000000000..730cb2df19 --- /dev/null +++ b/toolkit/mozapps/preferences/changemp.xhtml @@ -0,0 +1,96 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?> + +<window + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + style="min-width: 40em" + onload="init()" + data-l10n-id="primary-password-dialog" +> + <dialog id="changemp"> + <script src="chrome://mozapps/content/preferences/changemp.js" /> + + <linkset> + <html:link rel="localization" href="branding/brand.ftl" /> + <html:link + rel="localization" + href="toolkit/preferences/preferences.ftl" + /> + </linkset> + + <description + id="admin" + class="header" + data-l10n-id="primary-password-admin" + hidden="true" + ></description> + <description + control="pw1" + data-l10n-id="primary-password-description" + ></description> + + <vbox> + <hbox> + <label + flex="1" + control="oldpw" + data-l10n-id="set-password-old-password" + ></label> + <html:input id="oldpw" type="password" /> + <!-- This textbox is inserted as a workaround to the fact that making the 'type' + & 'disabled' property of the 'oldpw' textbox toggle between ['password' & + 'false'] and ['text' & 'true'] - as would be necessary if the menu has more + than one tokens, some initialized and some not - does not work properly. So, + either the textbox 'oldpw' or the textbox 'message' would be displayed, + depending on the state of the token selected + --> + <html:input + type="text" + data-l10n-attrs="value" + data-l10n-id="password-not-set" + id="message" + disabled="true" + /> + </hbox> + <hbox> + <label + flex="1" + control="pw1" + data-l10n-id="set-password-new-password" + ></label> + <html:input + id="pw1" + type="password" + oninput="setPasswordStrength(); checkPasswords();" + /> + </hbox> + <hbox> + <label + flex="1" + control="pw2" + data-l10n-id="set-password-reenter-password" + ></label> + <html:input id="pw2" type="password" oninput="checkPasswords();" /> + </hbox> + </vbox> + + <html:label + for="pwmeter" + style="display: flex" + data-l10n-id="set-password-meter" + ></html:label> + <html:progress id="pwmeter" value="0" max="100" /> + + <description + control="pw2" + class="header" + data-l10n-id="primary-password-warning" + ></description> + </dialog> +</window> diff --git a/toolkit/mozapps/preferences/fontbuilder.js b/toolkit/mozapps/preferences/fontbuilder.js new file mode 100644 index 0000000000..5e264bfa53 --- /dev/null +++ b/toolkit/mozapps/preferences/fontbuilder.js @@ -0,0 +1,120 @@ +// -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* import-globals-from ../../content/preferencesBindings.js */ + +var FontBuilder = { + _enumerator: null, + get enumerator() { + if (!this._enumerator) { + this._enumerator = Cc["@mozilla.org/gfx/fontenumerator;1"].createInstance( + Ci.nsIFontEnumerator + ); + } + return this._enumerator; + }, + + _allFonts: null, + _langGroupSupported: false, + async buildFontList(aLanguage, aFontType, aMenuList) { + // Remove the original <menupopup> + if (aMenuList.menupopup) { + aMenuList.menupopup.remove(); + } + + let defaultFont = null; + // Load Font Lists + let fonts = await this.enumerator.EnumerateFontsAsync(aLanguage, aFontType); + if (fonts.length) { + defaultFont = this.enumerator.getDefaultFont(aLanguage, aFontType); + } else { + fonts = await this.enumerator.EnumerateFontsAsync(aLanguage, ""); + if (fonts.length) { + defaultFont = this.enumerator.getDefaultFont(aLanguage, ""); + } + } + + if (!this._allFonts) { + this._allFonts = await this.enumerator.EnumerateAllFontsAsync({}); + } + + // Build the UI for the Default Font and Fonts for this CSS type. + const popup = document.createXULElement("menupopup"); + let separator; + if (fonts.length) { + let menuitem = document.createXULElement("menuitem"); + if (defaultFont) { + document.l10n.setAttributes(menuitem, "fonts-label-default", { + name: defaultFont, + }); + } else { + document.l10n.setAttributes(menuitem, "fonts-label-default-unnamed"); + } + menuitem.setAttribute("value", ""); // Default Font has a blank value + popup.appendChild(menuitem); + + separator = document.createXULElement("menuseparator"); + popup.appendChild(separator); + + for (let font of fonts) { + menuitem = document.createXULElement("menuitem"); + menuitem.setAttribute("value", font); + menuitem.setAttribute("label", font); + popup.appendChild(menuitem); + } + } + + // Build the UI for the remaining fonts. + if (this._allFonts.length > fonts.length) { + this._langGroupSupported = true; + // Both lists are sorted, and the Fonts-By-Type list is a subset of the + // All-Fonts list, so walk both lists side-by-side, skipping values we've + // already created menu items for. + let builtItem = separator ? separator.nextSibling : popup.firstChild; + let builtItemValue = builtItem ? builtItem.getAttribute("value") : null; + + separator = document.createXULElement("menuseparator"); + popup.appendChild(separator); + + for (let font of this._allFonts) { + if (font != builtItemValue) { + const menuitem = document.createXULElement("menuitem"); + menuitem.setAttribute("value", font); + menuitem.setAttribute("label", font); + popup.appendChild(menuitem); + } else { + builtItem = builtItem.nextSibling; + builtItemValue = builtItem ? builtItem.getAttribute("value") : null; + } + } + } + aMenuList.appendChild(popup); + }, + + readFontSelection(aElement) { + // Determine the appropriate value to select, for the following cases: + // - there is no setting + // - the font selected by the user is no longer present (e.g. deleted from + // fonts folder) + const preference = Preferences.get(aElement.getAttribute("preference")); + if (preference.value) { + const fontItems = aElement.getElementsByAttribute( + "value", + preference.value + ); + + // There is a setting that actually is in the list. Respect it. + if (fontItems.length) { + return undefined; + } + } + + // Otherwise, use "default" font of current system which is computed + // with "font.name-list.*". If "font.name.*" is empty string, it means + // "default". So, return empty string in this case. + return ""; + }, +}; diff --git a/toolkit/mozapps/preferences/jar.mn b/toolkit/mozapps/preferences/jar.mn new file mode 100644 index 0000000000..0c41ea0c79 --- /dev/null +++ b/toolkit/mozapps/preferences/jar.mn @@ -0,0 +1,11 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +toolkit.jar: +% content mozapps %content/mozapps/ + content/mozapps/preferences/fontbuilder.js + content/mozapps/preferences/changemp.js + content/mozapps/preferences/changemp.xhtml + content/mozapps/preferences/removemp.js + content/mozapps/preferences/removemp.xhtml diff --git a/toolkit/mozapps/preferences/moz.build b/toolkit/mozapps/preferences/moz.build new file mode 100644 index 0000000000..199926b764 --- /dev/null +++ b/toolkit/mozapps/preferences/moz.build @@ -0,0 +1,10 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +with Files("**"): + BUG_COMPONENT = ("Toolkit", "Preferences") + +JAR_MANIFESTS += ["jar.mn"] diff --git a/toolkit/mozapps/preferences/removemp.js b/toolkit/mozapps/preferences/removemp.js new file mode 100644 index 0000000000..a5cf729459 --- /dev/null +++ b/toolkit/mozapps/preferences/removemp.js @@ -0,0 +1,52 @@ +// -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var gRemovePasswordDialog = { + _token: null, + _okButton: null, + _password: null, + init() { + this._okButton = document.getElementById("removemp").getButton("accept"); + document.l10n.setAttributes(this._okButton, "pw-remove-button"); + + this._password = document.getElementById("password"); + + var pk11db = Cc["@mozilla.org/security/pk11tokendb;1"].getService( + Ci.nsIPK11TokenDB + ); + this._token = pk11db.getInternalKeyToken(); + + // Initialize the enabled state of the Remove button by checking the + // initial value of the password ("" should be incorrect). + this.validateInput(); + document.addEventListener("dialogaccept", function () { + gRemovePasswordDialog.removePassword(); + }); + }, + + validateInput() { + this._okButton.disabled = !this._token.checkPassword(this._password.value); + }, + + async createAlert(titleL10nId, messageL10nId) { + const [title, message] = await document.l10n.formatValues([ + { id: titleL10nId }, + { id: messageL10nId }, + ]); + Services.prompt.alert(window, title, message); + }, + + removePassword() { + if (this._token.checkPassword(this._password.value)) { + this._token.changePassword(this._password.value, ""); + this.createAlert("pw-change-success-title", "settings-pp-erased-ok"); + } else { + this._password.value = ""; + this._password.focus(); + this.createAlert("pw-change-failed-title", "incorrect-pp"); + } + }, +}; diff --git a/toolkit/mozapps/preferences/removemp.xhtml b/toolkit/mozapps/preferences/removemp.xhtml new file mode 100644 index 0000000000..c4830f0045 --- /dev/null +++ b/toolkit/mozapps/preferences/removemp.xhtml @@ -0,0 +1,54 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?> + +<window + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + style="min-width: 35em" + onload="gRemovePasswordDialog.init()" + data-l10n-id="remove-primary-password" +> + <dialog id="removemp"> + <script src="chrome://mozapps/content/preferences/removemp.js" /> + + <linkset> + <html:link rel="localization" href="branding/brand.ftl" /> + <html:link + rel="localization" + href="toolkit/preferences/preferences.ftl" + /> + </linkset> + + <vbox id="warnings"> + <description + data-l10n-id="remove-primary-password-warning1" + ></description> + <description + class="header" + data-l10n-id="remove-primary-password-warning2" + ></description> + </vbox> + + <separator class="thin" /> + + <groupbox> + <label data-l10n-id="remove-info" /> + + <hbox align="center"> + <label control="password" data-l10n-id="remove-password-old-password" /> + <html:input + id="password" + type="password" + oninput="gRemovePasswordDialog.validateInput();" + aria-describedby="warnings" + /> + </hbox> + </groupbox> + + <separator /> + </dialog> +</window> |