This commit is contained in:
Justin Dolske 2008-10-10 21:42:19 -07:00
Родитель edbc7946d5 ce9c0a6be7
Коммит 0374ec8e2e
9 изменённых файлов: 100 добавлений и 330 удалений

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

@ -871,11 +871,26 @@ LoginManager.prototype = {
if (existingLogin) { if (existingLogin) {
this.log("Found an existing login matching this form submission"); this.log("Found an existing login matching this form submission");
// Change password if needed. /*
* Change password if needed.
*
* If the login has a username, change the password w/o prompting
* (because we can be fairly sure there's only one password
* associated with the username). But for logins without a
* username, ask the user... Some sites use a password-only "login"
* in different contexts (enter your PIN, answer a security
* question, etc), and without a username we can't be sure if
* modifying an existing login is the right thing to do.
*/
if (existingLogin.password != formLogin.password) { if (existingLogin.password != formLogin.password) {
this.log("...passwords differ, prompting to change."); if (formLogin.username) {
prompter = getPrompter(win); this.log("...Updating password for existing login.");
prompter.promptToChangePassword(existingLogin, formLogin); this.modifyLogin(existingLogin, formLogin);
} else {
this.log("...passwords differ, prompting to change.");
prompter = getPrompter(win);
prompter.promptToChangePassword(existingLogin, formLogin);
}
} }
return; return;

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

@ -429,7 +429,7 @@ LoginManagerPrompter.prototype = {
// be prompted for authentication again, which brings us here. // be prompted for authentication again, which brings us here.
var notifyBox = this._getNotifyBox(); var notifyBox = this._getNotifyBox();
if (notifyBox) if (notifyBox)
this._removeLoginNotifications(notifyBox); this._removeSaveLoginNotification(notifyBox);
var [hostname, httpRealm] = this._getAuthTarget(aChannel, aAuthInfo); var [hostname, httpRealm] = this._getAuthTarget(aChannel, aAuthInfo);
@ -503,11 +503,8 @@ LoginManagerPrompter.prototype = {
this.log("Updating password for " + username + this.log("Updating password for " + username +
" @ " + hostname + " (" + httpRealm + ")"); " @ " + hostname + " (" + httpRealm + ")");
if (notifyBox) // update password
this._showChangeLoginNotification(notifyBox, this._pwmgr.modifyLogin(selectedLogin, newLogin);
selectedLogin, newLogin);
else
this._pwmgr.modifyLogin(selectedLogin, newLogin);
} else { } else {
this.log("Login unchanged, no further action needed."); this.log("Login unchanged, no further action needed.");
@ -667,21 +664,17 @@ LoginManagerPrompter.prototype = {
/* /*
* _removeLoginNotifications * _removeSaveLoginNotification
* *
*/ */
_removeLoginNotifications : function (aNotifyBox) { _removeSaveLoginNotification : function (aNotifyBox) {
var oldBar = aNotifyBox.getNotificationWithValue("password-save"); var oldBar = aNotifyBox.getNotificationWithValue("password-save");
if (oldBar) { if (oldBar) {
this.log("Removing save-password notification bar."); this.log("Removing save-password notification bar.");
aNotifyBox.removeNotification(oldBar); aNotifyBox.removeNotification(oldBar);
} }
oldBar = aNotifyBox.getNotificationWithValue("password-change");
if (oldBar) {
this.log("Removing change-password notification bar.");
aNotifyBox.removeNotification(oldBar);
}
}, },

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

@ -77,7 +77,6 @@ MOCHI_TESTS = \
MOCHI_CONTENT = \ MOCHI_CONTENT = \
pwmgr_common.js \ pwmgr_common.js \
prompt_common.js \ prompt_common.js \
notification_common.js \
authenticate.sjs \ authenticate.sjs \
formsubmit.sjs \ formsubmit.sjs \
subtst_notifications_1.html \ subtst_notifications_1.html \
@ -86,9 +85,6 @@ MOCHI_CONTENT = \
subtst_notifications_4.html \ subtst_notifications_4.html \
subtst_notifications_5.html \ subtst_notifications_5.html \
subtst_notifications_6.html \ subtst_notifications_6.html \
subtst_notifications_8.html \
subtst_notifications_9.html \
subtst_notifications_10.html \
$(NULL) $(NULL)
XPCSHELL_TESTS = unit XPCSHELL_TESTS = unit

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

@ -1,54 +0,0 @@
/*
* getNotificationBox
*
* Fetches the notification box for the specified window.
*/
function getNotificationBox(aWindow) {
var chromeWin = aWindow
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow)
.QueryInterface(Ci.nsIDOMChromeWindow);
// Don't need .wrappedJSObject here, unlike when chrome does this.
var notifyBox = chromeWin.getNotificationBox(aWindow);
return notifyBox;
}
/*
* getNotificationBar
*
*/
function getNotificationBar(aBox, aKind) {
ok(true, "Looking for " + aKind + " notification bar");
// Sometimes callers wants a bar, sometimes not. Allow 0 or 1, but not 2+.
ok(aBox.allNotifications.length <= 1, "Checking for multiple notifications");
return aBox.getNotificationWithValue(aKind);
}
/*
* clickNotificationButton
*
* Clicks the specified notification button.
*/
function clickNotificationButton(aBar, aButtonName) {
// This is a bit of a hack. The notification doesn't have an API to
// trigger buttons, so we dive down into the implementation and twiddle
// the buttons directly.
var buttons = aBar.getElementsByTagName("button");
var clicked = false;
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].label == aButtonName) {
buttons[i].click();
clicked = true;
break;
}
}
ok(clicked, "Clicked \"" + aButtonName + "\" button");
}

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

@ -1,25 +0,0 @@
<html>
<head>
<title>Subtest for Login Manager notifications</title>
</head>
<body>
<h2>Subtest 10</h2>
<form id="form" action="formsubmit.sjs">
<input id="pass" name="pass" type="password">
<button type='submit'>Submit</button>
</form>
<script>
function submitForm() {
passField.value = "notifyp1";
form.submit();
}
window.onload = submitForm;
var form = document.getElementById("form");
var userField = document.getElementById("user");
var passField = document.getElementById("pass");
</script>
</body>
</html>

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

@ -1,27 +0,0 @@
<html>
<head>
<title>Subtest for Login Manager notifications</title>
</head>
<body>
<h2>Subtest 8</h2>
<form id="form" action="formsubmit.sjs">
<input id="user" name="user">
<input id="pass" name="pass" type="password">
<button type='submit'>Submit</button>
</form>
<script>
function submitForm() {
userField.value = "notifyu1";
passField.value = "pass2";
form.submit();
}
window.onload = submitForm;
var form = document.getElementById("form");
var userField = document.getElementById("user");
var passField = document.getElementById("pass");
</script>
</body>
</html>

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

@ -1,27 +0,0 @@
<html>
<head>
<title>Subtest for Login Manager notifications</title>
</head>
<body>
<h2>Subtest 9</h2>
<form id="form" action="formsubmit.sjs">
<input id="user" name="user">
<input id="pass" name="pass" type="password">
<button type='submit'>Submit</button>
</form>
<script>
function submitForm() {
userField.value = "";
passField.value = "pass2";
form.submit();
}
window.onload = submitForm;
var form = document.getElementById("form");
var userField = document.getElementById("user");
var passField = document.getElementById("pass");
</script>
</body>
</html>

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

@ -5,7 +5,6 @@
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script> <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="pwmgr_common.js"></script> <script type="text/javascript" src="pwmgr_common.js"></script>
<script type="text/javascript" src="notification_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head> </head>
<body> <body>
@ -37,13 +36,79 @@ var subtests = [
"subtst_notifications_1.html", // 13 "subtst_notifications_1.html", // 13
"subtst_notifications_6.html", // 14 "subtst_notifications_6.html", // 14
"subtst_notifications_1.html", // 15 "subtst_notifications_1.html", // 15
"subtst_notifications_6.html", // 16 "subtst_notifications_6.html"
"subtst_notifications_8.html", // 17
"subtst_notifications_8.html", // 18
"subtst_notifications_9.html", // 19
"subtst_notifications_10.html" // 20
]; ];
/*
* getNotificationBox
*
* Fetches the notification box for the specified window.
*/
function getNotificationBox(aWindow) {
/*
var chromeWin = aWindow
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
// Don't need .wrappedJSObject here, unlike when chrome does this.
var browserWin = chromeWin.browserDOMWindow;
var notifyBox = browserWin.getNotificationBox(aWindow);
return notifyBox;
*/
// Find the <browser> which contains aWindow, by looking
// through all the open windows and all the <browsers> in each.
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
var enumerator = wm.getEnumerator("navigator:browser");
var tabbrowser = null;
var foundBrowser = null;
while (!foundBrowser && enumerator.hasMoreElements()) {
var win = enumerator.getNext();
tabbrowser = win.getBrowser();
foundBrowser = tabbrowser.getBrowserForDocument(aWindow.document);
}
// Return the notificationBox associated with the browser.
return tabbrowser.getNotificationBox(foundBrowser);
}
/*
* getNotificationBar
*
*/
function getNotificationBar(aBox, aKind) {
ok(true, "Looking for " + aKind + " notification bar");
return aBox.getNotificationWithValue(aKind);
}
/*
* clickNotificationButton
*
* Clicks the specified notification button.
*/
function clickNotificationButton(aBar, aButtonName) {
// This is a bit of a hack. The notification doesn't have an API to
// trigger buttons, so we dive down into the implementation and twiddle
// the buttons directly.
var buttons = aBar.getElementsByTagName("button");
var clicked = false;
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].label == aButtonName) {
buttons[i].click();
clicked = true;
break;
}
}
ok(clicked, "Clicked \"" + aButtonName + "\" button");
}
var ignoreLoad = false; var ignoreLoad = false;
function handleLoad(aEvent) { function handleLoad(aEvent) {
@ -257,59 +322,6 @@ function checkTest() {
ok(bar, "got notification bar"); ok(bar, "got notification bar");
clickNotificationButton(bar, "Not Now"); clickNotificationButton(bar, "Not Now");
pwmgr.removeLogin(login1B); pwmgr.removeLogin(login1B);
// Add login for the next tests
pwmgr.addLogin(login1);
break;
case 17:
// Check for change-password bar, u+p login on u+p form. (not changed)
is(gotUser, "notifyu1", "Checking submitted username");
is(gotPass, "pass2", "Checking submitted password");
bar = getNotificationBar(notifyBox, "password-change");
ok(bar, "got notification bar");
clickNotificationButton(bar, "Don't Change");
break;
case 18:
// Check for change-password bar, u+p login on u+p form.
is(gotUser, "notifyu1", "Checking submitted username");
is(gotPass, "pass2", "Checking submitted password");
bar = getNotificationBar(notifyBox, "password-change");
ok(bar, "got notification bar");
clickNotificationButton(bar, "Change");
// cleanup
login1.password = "pass2";
pwmgr.removeLogin(login1);
login1.password = "notifyp1";
// Add login for the next test
pwmgr.addLogin(login2);
break;
// ...can't change a u+p login on a p-only form...
case 19:
// Check for change-password bar, p-only login on u+p form.
// (needed a different subtest for this because the login created in
// test_0init was interfering)
is(gotUser, "", "Checking submitted username");
is(gotPass, "pass2", "Checking submitted password");
bar = getNotificationBar(notifyBox, "password-change");
ok(bar, "got notification bar");
clickNotificationButton(bar, "Change");
break;
case 20:
// Check for change-password bar, p-only login on p-only form.
is(gotUser, "null", "Checking submitted username");
is(gotPass, "notifyp1", "Checking submitted password");
bar = getNotificationBar(notifyBox, "password-change");
ok(bar, "got notification bar");
clickNotificationButton(bar, "Change");
pwmgr.removeLogin(login2);
break; break;
default: default:

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

@ -6,7 +6,6 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="pwmgr_common.js"></script> <script type="text/javascript" src="pwmgr_common.js"></script>
<script type="text/javascript" src="prompt_common.js"></script> <script type="text/javascript" src="prompt_common.js"></script>
<script type="text/javascript" src="notification_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head> </head>
<body> <body>
@ -23,15 +22,12 @@ Login Manager test: username/password prompts
/** Test for Login Manager: username / password prompts. **/ /** Test for Login Manager: username / password prompts. **/
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var pwmgr, tmplogin, login1, login2A, login2B, login3A, login3B, login4; var pwmgr, login1, login2A, login2B, login3A, login3B;
function initLogins() { function initLogins() {
pwmgr = Cc["@mozilla.org/login-manager;1"]. pwmgr = Cc["@mozilla.org/login-manager;1"].
getService(Ci.nsILoginManager); getService(Ci.nsILoginManager);
tmpLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login1 = Cc["@mozilla.org/login-manager/loginInfo;1"]. login1 = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo); createInstance(Ci.nsILoginInfo);
login2A = Cc["@mozilla.org/login-manager/loginInfo;1"]. login2A = Cc["@mozilla.org/login-manager/loginInfo;1"].
@ -42,8 +38,6 @@ function initLogins() {
createInstance(Ci.nsILoginInfo); createInstance(Ci.nsILoginInfo);
login3B = Cc["@mozilla.org/login-manager/loginInfo;1"]. login3B = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo); createInstance(Ci.nsILoginInfo);
login4 = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login1.init("http://example.com", null, "http://example.com", login1.init("http://example.com", null, "http://example.com",
"", "examplepass", "", ""); "", "examplepass", "", "");
@ -51,19 +45,17 @@ function initLogins() {
"user1name", "user1pass", "", ""); "user1name", "user1pass", "", "");
login2B.init("http://example2.com", null, "http://example2.com", login2B.init("http://example2.com", null, "http://example2.com",
"user2name", "user2pass", "", ""); "user2name", "user2pass", "", "");
login3A.init("http://localhost:8888", null, "mochitest", login3A.init("http://localhost:8888", null, "mochitest",
"mochiuser1", "mochipass1", "", ""); "mochiuser1", "mochipass1", "", "");
login3B.init("http://localhost:8888", null, "mochitest2", login3B.init("http://localhost:8888", null, "mochitest2",
"mochiuser2", "mochipass2", "", ""); "mochiuser2", "mochipass2", "", "");
login4.init("http://localhost:8888", null, "mochitest3",
"mochiuser3", "mochipass3-old", "", "");
pwmgr.addLogin(login1); pwmgr.addLogin(login1);
pwmgr.addLogin(login2A); pwmgr.addLogin(login2A);
pwmgr.addLogin(login2B); pwmgr.addLogin(login2B);
pwmgr.addLogin(login3A); pwmgr.addLogin(login3A);
pwmgr.addLogin(login3B); pwmgr.addLogin(login3B);
pwmgr.addLogin(login4);
} }
function finishTest() { function finishTest() {
@ -73,19 +65,10 @@ function finishTest() {
pwmgr.removeLogin(login2B); pwmgr.removeLogin(login2B);
pwmgr.removeLogin(login3A); pwmgr.removeLogin(login3A);
pwmgr.removeLogin(login3B); pwmgr.removeLogin(login3B);
pwmgr.removeLogin(login4);
SimpleTest.finish(); SimpleTest.finish();
} }
/*
* handleDialog
*
* Invoked a short period of time after calling startCallbackTimer(), and
* allows testing the actual auth dialog while it's being displayed. Tests
* should call startCallbackTimer() each time the auth dialog is expected (the
* timer is a one-shot).
*/
function handleDialog(doc, testNum) { function handleDialog(doc, testNum) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
ok(true, "handleDialog running for test " + testNum); ok(true, "handleDialog running for test " + testNum);
@ -252,27 +235,6 @@ function handleDialog(doc, testNum) {
is(password, "mochipass2", "Checking filled password"); is(password, "mochipass2", "Checking filled password");
break; break;
// (1002 doesn't trigger a dialog)
case 1003:
is(username, "mochiuser1", "Checking filled username");
is(password, "mochipass1", "Checking filled password");
passfield.setAttribute("value", "mochipass1-new");
break;
case 1004:
is(username, "mochiuser3", "Checking filled username");
is(password, "mochipass3-old", "Checking filled password");
passfield.setAttribute("value", "mochipass3-new");
break;
case 1005:
is(username, "", "Checking filled username");
is(password, "", "Checking filled password");
userfield.setAttribute("value", "mochiuser3");
passfield.setAttribute("value", "mochipass3-old");
break;
default: default:
ok(false, "Uhh, unhandled switch for testNum #" + testNum); ok(false, "Uhh, unhandled switch for testNum #" + testNum);
break; break;
@ -288,11 +250,6 @@ function handleDialog(doc, testNum) {
} }
/*
* handleLoad
*
* Called when a load event is fired at the subtest's iframe.
*/
function handleLoad() { function handleLoad() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
ok(true, "handleLoad running for test " + testNum); ok(true, "handleLoad running for test " + testNum);
@ -338,69 +295,6 @@ function handleLoad() {
is(username, "mochiuser1", "Checking for echoed username"); is(username, "mochiuser1", "Checking for echoed username");
is(password, "mochipass1", "Checking for echoed password"); is(password, "mochipass1", "Checking for echoed password");
// Same realm we've already authenticated to, but with a different
// expected password (to trigger an auth prompt, and change-password
// notification bar).
startCallbackTimer();
iframe.src = "authenticate.sjs?user=mochiuser1&pass=mochipass1-new";
break;
case 1003:
testNum++;
is(authok, "PASS", "Checking for successful authentication");
is(username, "mochiuser1", "Checking for echoed username");
is(password, "mochipass1-new", "Checking for echoed password");
// Check for the notification bar, and change the password.
bar = getNotificationBar(notifyBox, "password-change");
ok(bar, "got notification bar");
clickNotificationButton(bar, "Change");
// Housekeeping: change it back
tmpLogin.init("http://localhost:8888", null, "mochitest",
"mochiuser1", "mochipass1-new", "", "");
pwmgr.modifyLogin(tmpLogin, login3A);
// Same as last test, but for a realm we haven't already authenticated
// to (but have an existing saved login for, so that we'll trigger
// a change-password notification bar.
startCallbackTimer();
iframe.src = "authenticate.sjs?user=mochiuser3&pass=mochipass3-new&realm=mochitest3";
break;
case 1004:
testNum++;
is(authok, "PASS", "Checking for successful authentication");
is(username, "mochiuser3", "Checking for echoed username");
is(password, "mochipass3-new", "Checking for echoed password");
// Check for the notification bar, and change the password.
bar = getNotificationBar(notifyBox, "password-change");
ok(bar, "got notification bar");
clickNotificationButton(bar, "Change");
// Housekeeping: change it back to the original login4. Actually,
// just delete it and we'll re-add it as the next test.
tmpLogin.init("http://localhost:8888", null, "mochitest3",
"mochiuser3", "mochipass3-new", "", "");
pwmgr.removeLogin(tmpLogin);
// Trigger a new prompt, so we can test adding a new login.
startCallbackTimer();
iframe.src = "authenticate.sjs?user=mochiuser3&pass=mochipass3-old&realm=mochitest3";
break;
case 1005:
testNum++;
is(authok, "PASS", "Checking for successful authentication");
is(username, "mochiuser3", "Checking for echoed username");
is(password, "mochipass3-old", "Checking for echoed password");
// Check for the notification bar, and change the password.
bar = getNotificationBar(notifyBox, "password-save");
ok(bar, "got notification bar");
clickNotificationButton(bar, "Remember");
finishTest(); finishTest();
break; break;
@ -443,14 +337,7 @@ var pword = { value : null };
var result = { value : null }; var result = { value : null };
var isOk; var isOk;
// The notification box (not *bar*) is a constant, per-tab container. So, we // XXX Add test for host that doesn't yet exist to test login-saving logic
// only need to fetch it once.
var notifyBox = getNotificationBox(window.top);
ok(notifyBox, "Got notification box");
// Remove any notification bars that might be left over from other tests.
notifyBox.removeAllNotifications(true);
// ===== test 1 ===== // ===== test 1 =====
var testNum = 1; var testNum = 1;