Bug 953875 - Use toolkit password manager, r=clokep.
This commit is contained in:
Родитель
5765ebd990
Коммит
72ad64fe67
|
@ -6,6 +6,10 @@ pref("messenger.startup.action", 1);
|
|||
|
||||
pref("messenger.accounts", "");
|
||||
|
||||
// Should the accounts service stored in the password manager the
|
||||
// passwords that are currently stored in the preferences?
|
||||
pref("messenger.accounts.convertOldPasswords", false);
|
||||
|
||||
// The intervals in seconds between automatic reconnection attempts
|
||||
// The last value will be reused forever.
|
||||
// A value of 0 means that there will be no more reconnection attempts.
|
||||
|
|
|
@ -241,7 +241,7 @@ interface imIAccount: prplIAccount {
|
|||
|
||||
attribute short firstConnectionState;
|
||||
|
||||
// FIXME password should be in password manager
|
||||
// Passwords are stored in the toolkit Password Manager.
|
||||
attribute AUTF8String password;
|
||||
|
||||
attribute AUTF8String alias;
|
||||
|
|
|
@ -47,11 +47,24 @@ const kAccountKeyPrefix = "account";
|
|||
const kAccountOptionPrefPrefix = "options.";
|
||||
const kPrefAccountName = "name";
|
||||
const kPrefAccountPrpl = "prpl";
|
||||
const kPrefAccountPassword = "password";
|
||||
const kPrefAccountAutoLogin = "autoLogin";
|
||||
const kPrefAccountAlias = "alias";
|
||||
const kPrefAccountFirstConnectionState = "firstConnectionState";
|
||||
|
||||
const kPrefConvertOldPasswords = "messenger.accounts.convertOldPasswords";
|
||||
const kPrefAccountPassword = "password";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "LoginManager", function()
|
||||
Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager)
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_", function()
|
||||
l10nHelper("chrome://chat/locale/accounts.properties")
|
||||
);
|
||||
|
||||
var gUserCanceledMasterPasswordPrompt = false;
|
||||
var gConvertingOldPasswords = false;
|
||||
|
||||
var SavePrefTimer = {
|
||||
saveNow: function() {
|
||||
if (this._timer) {
|
||||
|
@ -167,6 +180,17 @@ function imAccount(aKey, aName, aPrplId)
|
|||
if (this.firstConnectionState == Ci.imIAccount.FIRST_CONNECTION_PENDING)
|
||||
this.firstConnectionState = Ci.imIAccount.FIRST_CONNECTION_CRASHED;
|
||||
|
||||
// Try to convert old passwords stored in the preferences.
|
||||
// Don't try too hard if the user has canceled a master password prompt:
|
||||
// we don't want to display several of theses prompts at startup.
|
||||
if (gConvertingOldPasswords && !this.protocol.noPassword) {
|
||||
try {
|
||||
let password = this.prefBranch.getCharPref(kPrefAccountPassword);
|
||||
if (password && !this.password)
|
||||
this.password = password;
|
||||
} catch (e) { /* No password saved in the prefs for this account. */ }
|
||||
}
|
||||
|
||||
// Check for errors that should prevent connection attempts.
|
||||
if (this._passwordRequired && !this.password)
|
||||
this._connectionErrorReason = Ci.imIAccount.ERROR_MISSING_PASSWORD;
|
||||
|
@ -187,7 +211,9 @@ imAccount.prototype = {
|
|||
connectionErrorMessage: "",
|
||||
_connectionErrorReason: Ci.prplIAccount.NO_ERROR,
|
||||
get connectionErrorReason() {
|
||||
if (this._connectionErrorReason != Ci.prplIAccount.NO_ERROR)
|
||||
if (this._connectionErrorReason != Ci.prplIAccount.NO_ERROR &&
|
||||
(this._connectionErrorReason != Ci.imIAccount.ERROR_MISSING_PASSWORD ||
|
||||
!this._password))
|
||||
return this._connectionErrorReason;
|
||||
else
|
||||
return this.prplAccount.connectionErrorReason;
|
||||
|
@ -377,17 +403,77 @@ imAccount.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
_password: "",
|
||||
get password() {
|
||||
if (this._password)
|
||||
return this._password;
|
||||
|
||||
// Avoid prompting the user for the master password more than once at startup.
|
||||
if (gUserCanceledMasterPasswordPrompt)
|
||||
return "";
|
||||
|
||||
let passwordURI = "im://" + this.protocol.id;
|
||||
let logins;
|
||||
try {
|
||||
return this.prefBranch.getCharPref(kPrefAccountPassword);
|
||||
logins = LoginManager.findLogins({}, passwordURI, null, passwordURI);
|
||||
} catch (e) {
|
||||
this._handleMasterPasswordException(e);
|
||||
return "";
|
||||
}
|
||||
let normalizedName = this.normalizedName;
|
||||
for each (let login in logins) {
|
||||
if (login.username == normalizedName) {
|
||||
this._password = login.password;
|
||||
if (this._connectionErrorReason == Ci.imIAccount.ERROR_MISSING_PASSWORD) {
|
||||
// We have found a password for an account marked as missing password,
|
||||
// re-check all others accounts missing a password. But first,
|
||||
// remove the error on our own account to avoid re-checking it.
|
||||
delete this._connectionErrorReason;
|
||||
gAccountsService._checkIfPasswordStillMissing();
|
||||
}
|
||||
return this._password;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
},
|
||||
_checkIfPasswordStillMissing: function() {
|
||||
if (this._connectionErrorReason != Ci.imIAccount.ERROR_MISSING_PASSWORD ||
|
||||
!this.password)
|
||||
return;
|
||||
|
||||
delete this._connectionErrorReason;
|
||||
this._sendUpdateNotification();
|
||||
},
|
||||
get _passwordRequired()
|
||||
!this.protocol.noPassword && !this.protocol.passwordOptional,
|
||||
set password(aPassword) {
|
||||
this.prefBranch.setCharPref(kPrefAccountPassword, aPassword);
|
||||
this._password = aPassword;
|
||||
if (gUserCanceledMasterPasswordPrompt)
|
||||
return;
|
||||
let newLogin = Cc["@mozilla.org/login-manager/loginInfo;1"]
|
||||
.createInstance(Ci.nsILoginInfo);
|
||||
let passwordURI = "im://" + this.protocol.id;
|
||||
newLogin.init(passwordURI, null, passwordURI, this.normalizedName,
|
||||
aPassword, "", "");
|
||||
try {
|
||||
let logins = LoginManager.findLogins({}, passwordURI, null, passwordURI);
|
||||
let saved = false;
|
||||
for each (let login in logins) {
|
||||
if (newLogin.matches(login, true)) {
|
||||
if (aPassword)
|
||||
LoginManager.modifyLogin(login, newLogin);
|
||||
else
|
||||
LoginManager.removeLogin(login);
|
||||
saved = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!saved && aPassword)
|
||||
LoginManager.addLogin(newLogin);
|
||||
} catch (e) {
|
||||
this._handleMasterPasswordException(e);
|
||||
}
|
||||
|
||||
this._connectionInfoChanged();
|
||||
if (aPassword &&
|
||||
this._connectionErrorReason == Ci.imIAccount.ERROR_MISSING_PASSWORD)
|
||||
|
@ -396,6 +482,13 @@ imAccount.prototype = {
|
|||
this._connectionErrorReason = Ci.imIAccount.ERROR_MISSING_PASSWORD;
|
||||
this._sendUpdateNotification();
|
||||
},
|
||||
_handleMasterPasswordException: function(aException) {
|
||||
if (aException.result != Components.results.NS_ERROR_ABORT)
|
||||
throw aException;
|
||||
|
||||
gUserCanceledMasterPasswordPrompt = true;
|
||||
executeSoon(function () { gUserCanceledMasterPasswordPrompt = false; });
|
||||
},
|
||||
|
||||
get autoLogin() {
|
||||
let autoLogin = true;
|
||||
|
@ -435,6 +528,17 @@ imAccount.prototype = {
|
|||
},
|
||||
|
||||
remove: function() {
|
||||
let login = Cc["@mozilla.org/login-manager/loginInfo;1"]
|
||||
.createInstance(Ci.nsILoginInfo);
|
||||
let passwordURI = "im://" + this.protocol.id;
|
||||
login.init(passwordURI, null, passwordURI, this.normalizedName, "", "", "");
|
||||
let logins = LoginManager.findLogins({}, passwordURI, null, passwordURI);
|
||||
for each (let l in logins) {
|
||||
if (login.matches(l, true)) {
|
||||
LoginManager.removeLogin(l);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.unInit();
|
||||
Services.contacts.forgetAccount(this.numericId);
|
||||
this.prefBranch.deleteBranch("");
|
||||
|
@ -465,7 +569,33 @@ imAccount.prototype = {
|
|||
return this.prplAccount;
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
connect: function() { this._ensurePrplAccount.connect(); },
|
||||
connect: function() {
|
||||
if (this._passwordRequired) {
|
||||
// If the previous connection attempt failed because we have a wrong password,
|
||||
// clear the passwor cache so that if there's no password in the password
|
||||
// manager the user gets prompted again.
|
||||
if (this.connectionErrorReason == Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED)
|
||||
delete this._password;
|
||||
|
||||
let password = this.password;
|
||||
if (!password) {
|
||||
let prompts = Services.prompt;
|
||||
let shouldSave = {value: false};
|
||||
password = {value: ""};
|
||||
if (!prompts.promptPassword(null, _("passwordPromptTitle", this.name),
|
||||
_("passwordPromptText", this.name),
|
||||
password, _("passwordPromptSaveCheckbox"),
|
||||
shouldSave))
|
||||
return;
|
||||
|
||||
if (shouldSave.value)
|
||||
this.password = password.value;
|
||||
else
|
||||
this._password = password.value;
|
||||
}
|
||||
}
|
||||
this._ensurePrplAccount.connect();
|
||||
},
|
||||
disconnect: function() {
|
||||
if (this._statusObserver) {
|
||||
this.statusInfo.removeObserver(this._statusObserver);
|
||||
|
@ -545,12 +675,17 @@ imAccount.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
var gAccountsService = null;
|
||||
|
||||
function AccountsService() { }
|
||||
AccountsService.prototype = {
|
||||
initAccounts: function() {
|
||||
this._initAutoLoginStatus();
|
||||
this._accounts = [];
|
||||
this._accountsById = {};
|
||||
gAccountsService = this;
|
||||
gConvertingOldPasswords =
|
||||
Services.prefs.getBoolPref(kPrefConvertOldPasswords);
|
||||
let accountList = this._accountList;
|
||||
for each (let account in (accountList ? accountList.split(",") : [])) {
|
||||
try {
|
||||
|
@ -565,6 +700,11 @@ AccountsService.prototype = {
|
|||
dump(e + " " + e.toSource() + "\n");
|
||||
}
|
||||
}
|
||||
// If the user has canceled a master password prompt, we haven't
|
||||
// been able to save any password, so the old password conversion
|
||||
// still needs to happen.
|
||||
if (gConvertingOldPasswords && !gUserCanceledMasterPasswordPrompt)
|
||||
Services.prefs.setBoolPref(kPrefConvertOldPasswords, false);
|
||||
|
||||
this._prefObserver = this.observe.bind(this);
|
||||
Services.prefs.addObserver(kPrefMessengerAccounts, this._prefObserver, false);
|
||||
|
@ -597,6 +737,7 @@ AccountsService.prototype = {
|
|||
unInitAccounts: function() {
|
||||
for each (let account in this._accounts)
|
||||
account.unInit();
|
||||
gAccountsService = null;
|
||||
delete this._accounts;
|
||||
delete this._accountsById;
|
||||
Services.prefs.removeObserver(kPrefMessengerAccounts, this._prefObserver);
|
||||
|
@ -715,6 +856,18 @@ AccountsService.prototype = {
|
|||
Services.obs.notifyObservers(this, "autologin-processed", null);
|
||||
},
|
||||
|
||||
_checkingIfPasswordStillMissing: false,
|
||||
_checkIfPasswordStillMissing: function() {
|
||||
// Avoid recursion.
|
||||
if (this._checkingIfPasswordStillMissing)
|
||||
return;
|
||||
|
||||
this._checkingIfPasswordStillMissing = true;
|
||||
for each (let account in this._accounts)
|
||||
account._checkIfPasswordStillMissing();
|
||||
delete this._checkingIfPasswordStillMissing;
|
||||
},
|
||||
|
||||
getAccountById: function(aAccountId) {
|
||||
if (aAccountId.indexOf(kAccountKeyPrefix) != 0)
|
||||
throw Cr.NS_ERROR_INVALID_ARG;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
passwordPromptTitle=Password for %S
|
||||
passwordPromptText=Please enter your password for your account %S in order to connect it.
|
||||
passwordPromptSaveCheckbox=Use Password Manager to remember this password.
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
@AB_CD@.jar:
|
||||
% locale chat @AB_CD@ %locale/@AB_CD@/chat/
|
||||
locale/@AB_CD@/chat/accounts.properties (%accounts.properties)
|
||||
locale/@AB_CD@/chat/commands.properties (%commands.properties)
|
||||
locale/@AB_CD@/chat/conversations.properties (%conversations.properties)
|
||||
locale/@AB_CD@/chat/facebook.properties (%facebook.properties)
|
||||
|
|
|
@ -728,7 +728,7 @@ const GenericProtocolPrototype = {
|
|||
get noPassword() false,
|
||||
get newMailNotification() false,
|
||||
get imagesInIM() false,
|
||||
get passwordOptional() true,
|
||||
get passwordOptional() false,
|
||||
get usePointSize() true,
|
||||
get registerNoScreenName() false,
|
||||
get slashCommandsNative() false,
|
||||
|
|
|
@ -26,6 +26,7 @@ pref("general.autoScroll", true);
|
|||
// 2 = check multi/single line controls
|
||||
pref("layout.spellcheckDefault", 1);
|
||||
|
||||
pref("messenger.accounts.convertOldPasswords", true);
|
||||
pref("messenger.accounts.promptOnDelete", true);
|
||||
|
||||
pref("messenger.buddies.showOffline", false);
|
||||
|
|
|
@ -141,12 +141,14 @@
|
|||
text = bundle.getFormattedString(key + "UnknownPrpl",
|
||||
[account.protocol.id]);
|
||||
else if (errorReason == Ci.imIAccount.ERROR_MISSING_PASSWORD)
|
||||
text = bundle.getString(key + "MissingPassword");
|
||||
text = bundle.getString(key + "EnteringPasswordRequired");
|
||||
else if (errorReason == Ci.imIAccount.ERROR_CRASHED)
|
||||
text = bundle.getString(key + "CrashedAccount");
|
||||
else
|
||||
text = account.connectionErrorMessage;
|
||||
text = bundle.getFormattedString(key, [text]);
|
||||
|
||||
if (errorReason != Ci.imIAccount.ERROR_MISSING_PASSWORD)
|
||||
text = bundle.getFormattedString(key, [text]);
|
||||
|
||||
this.setAttribute("error", "true");
|
||||
var error = document.getAnonymousElementByAttribute(this, "anonid",
|
||||
|
|
|
@ -74,7 +74,6 @@
|
|||
<label value="&account.password;" control="password" flex="1"/>
|
||||
<textbox id="password" flex="1" type="password"/>
|
||||
</hbox>
|
||||
<checkbox id="rememberPassword" label="&account.rememberPassword;" hidden="true"/>
|
||||
|
||||
<separator class="groove"/>
|
||||
|
||||
|
|
|
@ -381,11 +381,13 @@ var accountWizard = {
|
|||
rows.appendChild(this.createSummaryRow(label, this.username));
|
||||
if (!this.proto.noPassword) {
|
||||
this.password = this.getValue("password");
|
||||
label = document.getElementById("passwordLabel").value;
|
||||
var pass = "";
|
||||
for (let i = 0; i < this.password.length; ++i)
|
||||
pass += "*";
|
||||
rows.appendChild(this.createSummaryRow(label, pass));
|
||||
if (this.password) {
|
||||
label = document.getElementById("passwordLabel").value;
|
||||
var pass = "";
|
||||
for (let i = 0; i < this.password.length; ++i)
|
||||
pass += "*";
|
||||
rows.appendChild(this.createSummaryRow(label, pass));
|
||||
}
|
||||
}
|
||||
this.alias = this.getValue("alias");
|
||||
if (this.alias) {
|
||||
|
@ -439,7 +441,7 @@ var accountWizard = {
|
|||
|
||||
createAccount: function aw_createAccount() {
|
||||
var acc = Services.accounts.createAccount(this.username, this.proto.id);
|
||||
if (!this.proto.noPassword)
|
||||
if (!this.proto.noPassword && this.password)
|
||||
acc.password = this.password;
|
||||
if (this.alias)
|
||||
acc.alias = this.alias;
|
||||
|
|
|
@ -98,6 +98,8 @@
|
|||
<label value="&accountPasswordField.label;" control="password" id="passwordLabel"/>
|
||||
<textbox id="password" type="password"/>
|
||||
</hbox>
|
||||
<separator/>
|
||||
<description id="passwordManagerDescription">&accountPasswordManager.label;</description>
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage id="accountadvanced" pageid="accountadvanced" next="accountsummary"
|
||||
|
|
|
@ -335,8 +335,7 @@ var gAccountManager = {
|
|||
let isCommandDisabled =
|
||||
(this.isOffline ||
|
||||
(account.disconnected &&
|
||||
(account.connectionErrorReason == Ci.imIAccount.ERROR_UNKNOWN_PRPL ||
|
||||
account.connectionErrorReason == Ci.imIAccount.ERROR_MISSING_PASSWORD)));
|
||||
account.connectionErrorReason == Ci.imIAccount.ERROR_UNKNOWN_PRPL));
|
||||
|
||||
[[activeCommandElt, isCommandDisabled],
|
||||
[document.getElementById("cmd_moveup"), accountList.selectedIndex == 0],
|
||||
|
|
|
@ -338,7 +338,6 @@ Account.prototype = {
|
|||
protocol: null,
|
||||
password: "",
|
||||
autoLogin: true,
|
||||
rememberPassword: true,
|
||||
alias: "",
|
||||
proxyInfo: null,
|
||||
connectionStageMsg: "",
|
||||
|
|
|
@ -39,6 +39,7 @@ var gPrivacyPane = {
|
|||
init: function ()
|
||||
{
|
||||
this.updateDisabledState();
|
||||
this._initMasterPasswordUI();
|
||||
},
|
||||
|
||||
updateDisabledState: function ()
|
||||
|
@ -90,5 +91,112 @@ var gPrivacyPane = {
|
|||
protocolSvc.loadUrl(uri);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes master password UI: the "use master password" checkbox, selects
|
||||
* the master password button to show, and enables/disables it as necessary.
|
||||
* The master password is controlled by various bits of NSS functionality,
|
||||
* so the UI for it can't be controlled by the normal preference bindings.
|
||||
*/
|
||||
_initMasterPasswordUI: function ()
|
||||
{
|
||||
var noMP = !this._masterPasswordSet();
|
||||
|
||||
document.getElementById("changeMasterPassword").disabled = noMP;
|
||||
|
||||
document.getElementById("useMasterPassword").checked = !noMP;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the user has a master password set and false otherwise.
|
||||
*/
|
||||
_masterPasswordSet: function ()
|
||||
{
|
||||
const Cc = Components.classes, Ci = Components.interfaces;
|
||||
var secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].
|
||||
getService(Ci.nsIPKCS11ModuleDB);
|
||||
var slot = secmodDB.findSlotByName("");
|
||||
if (slot) {
|
||||
var status = slot.status;
|
||||
var hasMP = status != Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED &&
|
||||
status != Ci.nsIPKCS11Slot.SLOT_READY;
|
||||
return hasMP;
|
||||
} else {
|
||||
// XXX I have no bloody idea what this means
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Enables/disables the master password button depending on the state of the
|
||||
* "use master password" checkbox, and prompts for master password removal
|
||||
* if one is set.
|
||||
*/
|
||||
updateMasterPasswordButton: function ()
|
||||
{
|
||||
var checkbox = document.getElementById("useMasterPassword");
|
||||
var button = document.getElementById("changeMasterPassword");
|
||||
button.disabled = !checkbox.checked;
|
||||
|
||||
// unchecking the checkbox should try to immediately remove the master
|
||||
// password, because it's impossible to non-destructively remove the master
|
||||
// password used to encrypt all the passwords without providing it (by
|
||||
// design), and it would be extremely odd to pop up that dialog when the
|
||||
// user closes the prefwindow and saves his settings
|
||||
if (!checkbox.checked)
|
||||
this._removeMasterPassword();
|
||||
else
|
||||
this.changeMasterPassword();
|
||||
|
||||
this._initMasterPasswordUI();
|
||||
},
|
||||
|
||||
/**
|
||||
* Displays the "remove master password" dialog to allow the user to remove
|
||||
* the current master password. When the dialog is dismissed, master password
|
||||
* UI is automatically updated.
|
||||
*/
|
||||
_removeMasterPassword: function ()
|
||||
{
|
||||
const Cc = Components.classes, Ci = Components.interfaces;
|
||||
var secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].
|
||||
getService(Ci.nsIPKCS11ModuleDB);
|
||||
if (secmodDB.isFIPSEnabled) {
|
||||
var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
|
||||
getService(Ci.nsIPromptService);
|
||||
var bundle = document.getElementById("bundlePreferences");
|
||||
promptService.alert(window,
|
||||
bundle.getString("pw_change_failed_title"),
|
||||
bundle.getString("pw_change2empty_in_fips_mode"));
|
||||
}
|
||||
else {
|
||||
document.documentElement.openSubDialog("chrome://mozapps/content/preferences/removemp.xul",
|
||||
"", null);
|
||||
}
|
||||
this._initMasterPasswordUI();
|
||||
},
|
||||
|
||||
/**
|
||||
* Displays a dialog in which the master password may be changed.
|
||||
*/
|
||||
changeMasterPassword: function ()
|
||||
{
|
||||
document.documentElement.openSubDialog("chrome://mozapps/content/preferences/changemp.xul",
|
||||
"", null);
|
||||
this._initMasterPasswordUI();
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the sites where the user has saved passwords and the associated
|
||||
* login information.
|
||||
*/
|
||||
showPasswords: function ()
|
||||
{
|
||||
document.documentElement.openWindow("Toolkit:PasswordManager",
|
||||
"chrome://passwordmgr/content/passwordManager.xul",
|
||||
"", null);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
<preference id="purple.logging.log_chats" name="purple.logging.log_chats" type="bool"/>
|
||||
<preference id="purple.logging.log_ims" name="purple.logging.log_ims" type="bool"/>
|
||||
<preference id="purple.logging.log_system" name="purple.logging.log_system" type="bool"/>
|
||||
<preference id="pref.privacy.disable_button.view_passwords" name="pref.privacy.disable_button.view_passwords" type="bool"/>
|
||||
</preferences>
|
||||
|
||||
<broadcaster id="idleReportingEnabled"/>
|
||||
|
@ -117,6 +118,32 @@
|
|||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
<!-- Passwords -->
|
||||
<groupbox id="passwordsGroup" orient="vertical">
|
||||
<caption label="&passwords.label;"/>
|
||||
|
||||
<description>&savedPasswords.intro;</description>
|
||||
<hbox>
|
||||
<spacer flex="1"/>
|
||||
<button label="&savedPasswords.label;" accesskey="&savedPasswords.accesskey;"
|
||||
oncommand="gPrivacyPane.showPasswords();"
|
||||
preference="pref.privacy.disable_button.view_passwords"/>
|
||||
</hbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<description>&masterPassword.intro;</description>
|
||||
<hbox>
|
||||
<checkbox id="useMasterPassword" flex="1"
|
||||
label="&useMasterPassword.label;" accesskey="&useMasterPassword.accesskey;"
|
||||
oncommand="gPrivacyPane.updateMasterPasswordButton();"/>
|
||||
|
||||
<button id="changeMasterPassword"
|
||||
label="&changeMasterPassword.label;" accesskey="&changeMasterPassword.accesskey;"
|
||||
oncommand="gPrivacyPane.changeMasterPassword();"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
</prefpane>
|
||||
|
||||
</overlay>
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
<!ENTITY account.advanced "Advanced Options">
|
||||
<!ENTITY account.name "Username:">
|
||||
<!ENTITY account.password "Password:">
|
||||
<!ENTITY account.rememberPassword "remember password">
|
||||
<!ENTITY account.alias "Alias:">
|
||||
<!ENTITY account.newMailNotification "Notify on new Mail">
|
||||
<!ENTITY account.autojoin "Auto-Joined Channels:">
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<!ENTITY accountPasswordTitle.label "Password">
|
||||
<!ENTITY accountPasswordInfo.label "Please enter your password in the box below.">
|
||||
<!ENTITY accountPasswordField.label "Password:">
|
||||
<!ENTITY accountPasswordManager.label "The password entered here will be stored in the Password Manager. Leave this box empty if you want to be prompted for your password each time this account is connected.">
|
||||
|
||||
<!ENTITY accountAdvancedTitle.label "Advanced Options">
|
||||
<!ENTITY accountAdvancedInfo.label "Feel free to skip this step if you want to.">
|
||||
|
|
|
@ -7,7 +7,7 @@ accountUsernameInfoWithDescription=Please enter the username (%S) for your %S ac
|
|||
|
||||
account.connection.error=Error: %S
|
||||
account.connection.errorUnknownPrpl= No '%S' protocol plugin.
|
||||
account.connection.errorMissingPassword=A password is required to connect this account.
|
||||
account.connection.errorEnteringPasswordRequired=Entering a password is required to connect this account.
|
||||
account.connection.errorCrashedAccount=A crash occurred while connecting this account.
|
||||
account.connection.progress=Connecting: %S…
|
||||
account.connecting=Connecting…
|
||||
|
|
|
@ -19,3 +19,14 @@
|
|||
<!ENTITY logShowFolder.description "Open the folder containing the record files">
|
||||
<!ENTITY logShowFolderButton.label "Show Log Folder…">
|
||||
<!ENTITY logShowFolderButton.accesskey "L">
|
||||
|
||||
<!-- Passwords, see mail/chrome/messenger/preferences/security.dtd -->
|
||||
<!ENTITY passwords.label "Passwords">
|
||||
<!ENTITY savedPasswords.intro "&brandShortName; can remember passwords for all of your accounts.">
|
||||
<!ENTITY useMasterPassword.label "Use a master password">
|
||||
<!ENTITY useMasterPassword.accesskey "U">
|
||||
<!ENTITY masterPassword.intro "A Master Password protects all your passwords, but you must enter it once per session.">
|
||||
<!ENTITY changeMasterPassword.label "Change Master Password…">
|
||||
<!ENTITY changeMasterPassword.accesskey "C">
|
||||
<!ENTITY savedPasswords.label "Saved Passwords…">
|
||||
<!ENTITY savedPasswords.accesskey "S">
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
<!ENTITY warnAddonInstall.label "Warn me when sites try to install add-ons">
|
||||
<!ENTITY warnAddonInstall.accesskey "W">
|
||||
|
||||
<!-- LOCALIZATION NOTE (blockWebForgeries.label, blockAttackSites.label):
|
||||
The methods by which forged (phished) and attack sites will be detected by
|
||||
phishing providers will vary from human review to machine-based heuristics to a
|
||||
combination of both, so it's important that these strings and
|
||||
useDownloadedList.label convey the meaning "reported" (and not something like
|
||||
"known").
|
||||
-->
|
||||
<!ENTITY blockAttackSites.label "Block reported attack sites">
|
||||
<!ENTITY blockAttackSites.accesskey "k">
|
||||
|
||||
<!ENTITY blockWebForgeries.label "Block reported web forgeries">
|
||||
<!ENTITY blockWebForgeries.accesskey "B">
|
||||
|
||||
<!ENTITY addonExceptions.label "Exceptions…">
|
||||
<!ENTITY addonExceptions.accesskey "E">
|
||||
|
||||
|
||||
<!ENTITY passwords.label "Passwords">
|
||||
|
||||
<!ENTITY rememberPasswords.label "Remember passwords for sites">
|
||||
<!ENTITY rememberPasswords.accesskey "R">
|
||||
<!ENTITY passwordExceptions.label "Exceptions…">
|
||||
<!ENTITY passwordExceptions.accesskey "x">
|
||||
|
||||
<!ENTITY useMasterPassword.label "Use a master password">
|
||||
<!ENTITY useMasterPassword.accesskey "U">
|
||||
<!ENTITY changeMasterPassword.label "Change Master Password…">
|
||||
<!ENTITY changeMasterPassword.accesskey "M">
|
||||
|
||||
<!ENTITY savedPasswords.label "Saved Passwords…">
|
||||
<!ENTITY savedPasswords.accesskey "P">
|
||||
|
||||
|
||||
<!ENTITY warnings.label "Warning Messages">
|
||||
|
||||
<!ENTITY chooseWarnings.label "Choose which warning messages you want to see while browsing the web">
|
||||
|
||||
<!ENTITY warningSettings.label "Settings…">
|
||||
<!ENTITY warningSettings.accesskey "S">
|
|
@ -37,7 +37,6 @@
|
|||
locale/@AB_CD@/instantbird/preferences/preferences.dtd (%chrome/instantbird/preferences/preferences.dtd)
|
||||
locale/@AB_CD@/instantbird/preferences/preferences.properties (%chrome/instantbird/preferences/preferences.properties)
|
||||
locale/@AB_CD@/instantbird/preferences/privacy.dtd (%chrome/instantbird/preferences/privacy.dtd)
|
||||
locale/@AB_CD@/instantbird/preferences/security.dtd (%chrome/instantbird/preferences/security.dtd)
|
||||
locale/@AB_CD@/instantbird/preferences/tabs.dtd (%chrome/instantbird/preferences/tabs.dtd)
|
||||
locale/@AB_CD@/instantbird/preferences/themes.dtd (%chrome/instantbird/preferences/themes.dtd)
|
||||
locale/@AB_CD@/instantbird/preferences/themes.properties (%chrome/instantbird/preferences/themes.properties)
|
||||
|
|
Загрузка…
Ссылка в новой задаче