Password manager should have mode to display saved password.

bug 78754, patch by vdvo@vdvo.net, r=neil, sr=bryner
This commit is contained in:
mvl%exedo.nl 2004-03-09 20:11:22 +00:00
Родитель a1dc195ac8
Коммит a9f062e472
4 изменённых файлов: 88 добавлений и 18 удалений

Просмотреть файл

@ -54,6 +54,7 @@ var isPasswordManager = (window.arguments[0] == "S");
// variables for encryption // variables for encryption
var encrypted = ""; var encrypted = "";
var showingPasswords = false;
function Startup() { function Startup() {
@ -110,6 +111,8 @@ function Startup() {
} }
LoadRejects(); LoadRejects();
// label the show/hide password button
document.getElementById("togglePasswords").label = kSignonBundle.getString(showingPasswords ? "hidePasswords" : "showPasswords");
} else { } else {
nopreviewsTree = document.getElementById("nopreviewsTree"); nopreviewsTree = document.getElementById("nopreviewsTree");
@ -178,6 +181,7 @@ var signonReloadDisplay = {
gSelectUserInUse = true; gSelectUserInUse = true;
document.getElementById("removeSignon").disabled = true; document.getElementById("removeSignon").disabled = true;
document.getElementById("removeAllSignons").disabled = true; document.getElementById("removeAllSignons").disabled = true;
document.getElementById("togglePasswords").disabled = true;
} else if (state == "resume") { } else if (state == "resume") {
gSelectUserInUse = false; gSelectUserInUse = false;
var selections = GetTreeSelections(signonsTree); var selections = GetTreeSelections(signonsTree);
@ -186,6 +190,7 @@ var signonReloadDisplay = {
} }
if (signons.length > 0) { if (signons.length > 0) {
document.getElementById("removeAllSignons").disabled = false; document.getElementById("removeAllSignons").disabled = false;
document.getElementById("togglePasswords").disabled = false;
} }
} else if (state == "inUse") { } else if (state == "inUse") {
gSelectUserInUse = true; gSelectUserInUse = true;
@ -198,34 +203,37 @@ var signonReloadDisplay = {
var signonsTreeView = { var signonsTreeView = {
rowCount : 0, rowCount : 0,
setTree : function(tree){}, setTree : function(tree) {},
getImageSrc : function(row,column) {}, getImageSrc : function(row,column) {},
getProgressMode : function(row,column) {}, getProgressMode : function(row,column) {},
getCellValue : function(row,column) {}, getCellValue : function(row,column) {},
getCellText : function(row,column){ getCellText : function(row,column) {
var rv=""; var rv="";
if (column=="siteCol") { if (column=="siteCol") {
rv = signons[row].host; rv = signons[row].host;
} else if (column=="userCol") { } else if (column=="userCol") {
rv = signons[row].user; rv = signons[row].user;
} else if (column=="passwordCol") {
rv = signons[row].password;
} }
return rv; return rv;
}, },
isSeparator : function(index) {return false;}, isSeparator : function(index) { return false; },
isSorted: function() { return false; }, isSorted : function() { return false; },
isContainer : function(index) {return false;}, isContainer : function(index) { return false; },
cycleHeader : function(aColId, aElt) {}, cycleHeader : function(aColId, aElt) {},
getRowProperties : function(row,column,prop){}, getRowProperties : function(row,column,prop) {},
getColumnProperties : function(column,columnElement,prop){}, getColumnProperties : function(column,columnElement,prop) {},
getCellProperties : function(row,prop){} getCellProperties : function(row,prop) {}
}; };
var signonsTree; var signonsTree;
function Signon(number, host, user, rawuser) { function Signon(number, host, user, rawuser, password) {
this.number = number; this.number = number;
this.host = host; this.host = host;
this.user = user; this.user = user;
this.rawuser = rawuser; this.rawuser = rawuser;
this.password = password;
} }
function LoadSignons() { function LoadSignons() {
@ -241,22 +249,19 @@ function LoadSignons() {
nextPassword = nextPassword.QueryInterface(Components.interfaces.nsIPassword); nextPassword = nextPassword.QueryInterface(Components.interfaces.nsIPassword);
var host = nextPassword.host; var host = nextPassword.host;
var user = nextPassword.user; var user = nextPassword.user;
var password = nextPassword.password;
var rawuser = user; var rawuser = user;
// if no username supplied, try to parse it out of the url // if no username supplied, try to parse it out of the url
if (user == "") { if (user == "") {
var unused = { };
var ioService = Components.classes["@mozilla.org/network/io-service;1"] var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService); .getService(Components.interfaces.nsIIOService);
var username;
try { try {
username = ioService.newURI(host, null, null).username; user = ioService.newURI(host, null, null).username;
if (user == "") {
user = "<>";
}
} catch(e) { } catch(e) {
username = "";
}
if (username != "") {
user = username;
} else {
user = "<>"; user = "<>";
} }
} }
@ -265,7 +270,7 @@ function LoadSignons() {
user = kSignonBundle.getFormattedString("encrypted", [user], 1); user = kSignonBundle.getFormattedString("encrypted", [user], 1);
} }
signons[count] = new Signon(count++, host, user, rawuser); signons[count] = new Signon(count++, host, user, rawuser, password);
} catch(e) { } catch(e) {
/* An entry is corrupt. Go to next element. */ /* An entry is corrupt. Go to next element. */
} }
@ -278,10 +283,13 @@ function LoadSignons() {
// disable "remove all signons" button if there are no signons // disable "remove all signons" button if there are no signons
var element = document.getElementById("removeAllSignons"); var element = document.getElementById("removeAllSignons");
var toggle = document.getElementById("togglePasswords")
if (signons.length == 0 || gSelectUserInUse) { if (signons.length == 0 || gSelectUserInUse) {
element.setAttribute("disabled","true"); element.setAttribute("disabled","true");
toggle.setAttribute("disabled","true");
} else { } else {
element.removeAttribute("disabled"); element.removeAttribute("disabled");
toggle.removeAttribute("disabled");
} }
return true; return true;
@ -308,6 +316,57 @@ function DeleteAllSignons() {
FinalizeSignonDeletions(); FinalizeSignonDeletions();
} }
function TogglePasswordVisible() {
if (!showingPasswords && !ConfirmShowPasswords())
return;
showingPasswords = !showingPasswords;
document.getElementById("togglePasswords").label = kSignonBundle.getString(showingPasswords ? "hidePasswords" : "showPasswords");
document.getElementById("passwordCol").hidden = !showingPasswords;
}
function AskUserShowPasswords() {
var prompter = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
var dummy = { value: false };
// Confirm the user wants to display passwords
return prompter.confirmEx(window,
null,
kSignonBundle.getString("noMasterPasswordPrompt"),
prompter.BUTTON_TITLE_YES * prompter.BUTTON_POS_0 + prompter.BUTTON_TITLE_NO * prompter.BUTTON_POS_1,
null, null, null, null, dummy) == 0; // 0=="Yes" button
}
function ConfirmShowPasswords() {
if (encrypted) {
// If signons are encrypted, force prompted login into Software Security Device
var tokendb = Components.classes["@mozilla.org/security/pk11tokendb;1"]
.createInstance(Components.interfaces.nsIPK11TokenDB);
var token = tokendb.getInternalKeyToken();
try {
// If signons are encrypted but there is no master password (it could have been changed to an empty string),
// still give the user a chance to opt-out of displaying passwords (like in the non-encrypted case).
// Regardless of whether the check succeeds or not, we still login to make sure we're properly authenticated.
// This is all right since login() will succeed without prompting the user for the (empty) master password.
if (token.checkPassword("") && !AskUserShowPasswords())
return false;
token.login(true); // 'true' means always prompt for token password. User will be prompted until
// clicking 'Cancel' or entering the correct password.
} catch (e) {
// An exception will be thrown if the user cancels the login prompt dialog.
// User is also logged out of Software Security Device.
;
}
return token.isLoggedIn();
} else {
// signons not encrypted, confirm the user wants to display passwords
return AskUserShowPasswords();
}
}
function FinalizeSignonDeletions() { function FinalizeSignonDeletions() {
for (var s=0; s<deletedSignons.length; s++) { for (var s=0; s<deletedSignons.length; s++) {
passwordmanager.removeUser(deletedSignons[s].host, deletedSignons[s].rawuser); passwordmanager.removeUser(deletedSignons[s].host, deletedSignons[s].rawuser);

Просмотреть файл

@ -67,6 +67,10 @@
<splitter class="tree-splitter"/> <splitter class="tree-splitter"/>
<treecol id="userCol" label="&treehead.username.label;" flex="2" <treecol id="userCol" label="&treehead.username.label;" flex="2"
onclick="SignonColumnSort('user');" persist="width"/> onclick="SignonColumnSort('user');" persist="width"/>
<splitter class="tree-splitter"/>
<treecol id="passwordCol" label="&treehead.password.label;" flex="2"
onclick="SignonColumnSort('password');" persist="width"
hidden="true"/>
</treecols> </treecols>
<treechildren/> <treechildren/>
</tree> </tree>
@ -77,6 +81,9 @@
<button id="removeAllSignons" <button id="removeAllSignons"
label="&removeall.label;" label="&removeall.label;"
oncommand="DeleteAllSignons();"/> oncommand="DeleteAllSignons();"/>
<spacer flex="1"/>
<button id="togglePasswords"
oncommand="TogglePasswordVisible();"/>
</hbox> </hbox>
</vbox> </vbox>
<!-- rejected signon sites --> <!-- rejected signon sites -->

Просмотреть файл

@ -12,5 +12,6 @@
<!ENTITY treehead.site.label "Site"> <!ENTITY treehead.site.label "Site">
<!ENTITY treehead.username.label "Username"> <!ENTITY treehead.username.label "Username">
<!ENTITY treehead.password.label "Password">
<!ENTITY remove.label "Remove"> <!ENTITY remove.label "Remove">
<!ENTITY removeall.label "Remove All"> <!ENTITY removeall.label "Remove All">

Просмотреть файл

@ -1,2 +1,5 @@
encrypted = %S (encrypted) encrypted = %S (encrypted)
close=Close close=Close
hidePasswords=Hide Passwords
showPasswords=Show Passwords
noMasterPasswordPrompt=Are you sure you wish to show your passwords?