Bug 362576 - autocomplete="off" should prevent filling passwords in addition to remembering passwords. r=gavin, ui-r=mconnor, a1.9=mconnor

This commit is contained in:
dolske@mozilla.com 2008-05-08 20:34:46 -07:00
Родитель 2d4376eda4
Коммит 64cba76577
4 изменённых файлов: 179 добавлений и 23 удалений

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

@ -715,6 +715,20 @@ LoginManager.prototype = {
},
/*
* _isAutoCompleteDisabled
*
* Returns true if the page requests autocomplete be disabled for the
* specified form input.
*/
_isAutocompleteDisabled : function (element) {
if (element && element.hasAttribute("autocomplete") &&
element.getAttribute("autocomplete").toLowerCase() == "off")
return true;
return false;
},
/*
* _onFormSubmit
*
@ -725,15 +739,6 @@ LoginManager.prototype = {
*/
_onFormSubmit : function (form) {
// local helper function
function autocompleteDisabled(element) {
if (element && element.hasAttribute("autocomplete") &&
element.getAttribute("autocomplete").toLowerCase() == "off")
return true;
return false;
};
// local helper function
function getPrompter(aWindow) {
var prompterSvc = Cc["@mozilla.org/login-manager/prompter;1"].
@ -769,10 +774,10 @@ LoginManager.prototype = {
// Check for autocomplete=off attribute. We don't use it to prevent
// autofilling (for existing logins), but won't save logins when it's
// present.
if (autocompleteDisabled(form) ||
autocompleteDisabled(usernameField) ||
autocompleteDisabled(newPasswordField) ||
autocompleteDisabled(oldPasswordField)) {
if (this._isAutocompleteDisabled(form) ||
this._isAutocompleteDisabled(usernameField) ||
this._isAutocompleteDisabled(newPasswordField) ||
this._isAutocompleteDisabled(oldPasswordField)) {
this.log("(form submission ignored -- autocomplete=off found)");
return;
}
@ -1014,7 +1019,20 @@ LoginManager.prototype = {
if (usernameField)
this._attachToInput(usernameField);
if (autofillForm) {
// If the form has an autocomplete=off attribute in play, don't
// fill in the login automatically. We check this after attaching
// the autocomplete stuff to the username field, so the user can
// still manually select a login to be filled in.
var isFormDisabled = false;
if (this._isAutocompleteDisabled(form) ||
this._isAutocompleteDisabled(usernameField) ||
this._isAutocompleteDisabled(passwordField)) {
isFormDisabled = true;
this.log("form[" + i + "]: not filled, has autocomplete=off");
}
if (autofillForm && !isFormDisabled) {
if (usernameField && usernameField.value) {
// If username was specified in the form, only fill in the

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

@ -15,14 +15,44 @@ Login Manager test: multiple login autocomplete
<!-- we presumably can't hide the content for this test. -->
<div id="content">
<!-- form1 tests multiple matching logins -->
<form id="form1" action="http://autocomplete:8888/formtest.js" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="pword">
<button type="submit">Submit</button>
<button type="reset"> Reset </button>
</form>
<!-- other forms test single logins, with autocomplete=off set -->
<form id="form2" action="http://autocomplete2" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="pword" autocomplete="off">
<button type="submit">Submit</button>
</form>
<form id="form3" action="http://autocomplete2" onsubmit="return false;">
<input type="text" name="uname" autocomplete="off">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
<form id="form4" action="http://autocomplete2" onsubmit="return false;" autocomplete="off">
<input type="text" name="uname">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
<form id="form5" action="http://autocomplete2" onsubmit="return false;">
<input type="text" name="uname" autocomplete="off">
<input type="password" name="pword" autocomplete="off">
<button type="submit">Submit</button>
</form>
<!-- control -->
<form id="form6" action="http://autocomplete2" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
</div>
<pre id="test">
@ -68,12 +98,18 @@ var login4 = new nsLoginInfo(
"http://localhost:8888", "http://autocomplete:8888", null,
"zzzuser4", "zzzpass4", "uname", "pword");
// login 5 only used in the single-user forms
var login5 = new nsLoginInfo(
"http://localhost:8888", "http://autocomplete2", null,
"singleuser5", "singlepass5", "uname", "pword");
// try/catch in case someone runs the tests manually, twice.
try {
pwmgr.addLogin(login1);
pwmgr.addLogin(login2);
pwmgr.addLogin(login3);
pwmgr.addLogin(login4);
pwmgr.addLogin(login5);
} catch (e) {
ok(false, "addLogin threw: " + e);
}
@ -89,8 +125,9 @@ function restoreForm() {
// Check for expected username/password in form.
function checkACForm(expectedUsername, expectedPassword) {
is(uname.value, expectedUsername, "Checking form username");
is(pword.value, expectedPassword, "Checking form password");
var formID = uname.parentNode.id;
is(uname.value, expectedUsername, "Checking " + formID + " username");
is(pword.value, expectedPassword, "Checking " + formID + " password");
}
@ -407,8 +444,100 @@ function runTest(testNum) {
checkACForm("", "");
numLogins = pwmgr.countLogins("http://localhost:8888", "http://autocomplete:8888", null);
is(numLogins, 0, "Correct number of logins after deleting one");
testNum = 99;
break;
/* Tests for single-user forms with autocomplete=off */
case 100:
// Turn our attention to form2
uname = $_(2, "uname");
pword = $_(2, "pword");
checkACForm("", "");
// Trigger autocomplete popup
restoreForm();
doKey("down");
break;
case 101:
// Check first entry
doKey("down");
checkACForm("", ""); // value shouldn't update
doKey("return"); // not "enter"!
checkACForm("singleuser5", "singlepass5");
break;
case 102:
// Turn our attention to form3
uname = $_(3, "uname");
pword = $_(3, "pword");
checkACForm("", "");
// Trigger autocomplete popup
restoreForm();
doKey("down");
break;
case 103:
// Check first entry
doKey("down");
checkACForm("", ""); // value shouldn't update
doKey("return"); // not "enter"!
checkACForm("singleuser5", "singlepass5");
break;
case 104:
// Turn our attention to form4
uname = $_(4, "uname");
pword = $_(4, "pword");
checkACForm("", "");
// Trigger autocomplete popup
restoreForm();
doKey("down");
break;
case 105:
// Check first entry
doKey("down");
checkACForm("", ""); // value shouldn't update
doKey("return"); // not "enter"!
checkACForm("singleuser5", "singlepass5");
break;
case 106:
// Turn our attention to form5
uname = $_(5, "uname");
pword = $_(5, "pword");
checkACForm("", "");
// Trigger autocomplete popup
restoreForm();
doKey("down");
break;
case 107:
// Check first entry
doKey("down");
checkACForm("", ""); // value shouldn't update
doKey("return"); // not "enter"!
checkACForm("singleuser5", "singlepass5");
break;
case 108:
// Turn our attention to form6
// (this is a control, w/o autocomplete=off, to ensure the login
// that was being suppressed would have been filled in otherwise)
uname = $_(6, "uname");
pword = $_(6, "pword");
checkACForm("singleuser5", "singlepass5");
/* FALLTHRU */
default:
pwmgr.removeLogin(login5);
SimpleTest.finish();
return;
}

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

@ -161,10 +161,13 @@ function startTest() {
numStartingLogins = countLogins();
ok(numStartingLogins > 0, "counting logins at start");
// Check first set of forms, which should be filled by pwmgr.
// Check first set of forms, which should not be filled by pwmgr.
for (var i = 1; i <= 7; i++) {
is($_(i, "uname").value, "testuser", "Checking for filled username " + i);
is($_(i, "pword").value, "testpass", "Checking for filled password " + i);
is($_(i, "uname").value, "", "Checking for unfilled username " + i);
is($_(i, "pword").value, "", "Checking for unfilled password " + i);
// Set the field values to that of an existing login
$_(i, "uname").value = "testuser";
$_(i, "pword").value = "testpass";
}
// Check second set of forms, which should have preset values (and are unknown to pwmgr).

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

@ -608,15 +608,21 @@ nsFormFillController::Focus(nsIDOMEvent* aEvent)
nsAutoString autocomplete;
input->GetAttribute(NS_LITERAL_STRING("autocomplete"), autocomplete);
PRInt32 dummy;
PRBool isPwmgrInput = PR_FALSE;
if (mPwmgrInputs.Get(input, &dummy))
isPwmgrInput = PR_TRUE;
if (type.LowerCaseEqualsLiteral("text") && !isReadOnly &&
!autocomplete.LowerCaseEqualsLiteral("off")) {
(!autocomplete.LowerCaseEqualsLiteral("off") || isPwmgrInput)) {
nsCOMPtr<nsIDOMHTMLFormElement> form;
input->GetForm(getter_AddRefs(form));
if (form)
form->GetAttribute(NS_LITERAL_STRING("autocomplete"), autocomplete);
if (!form || !autocomplete.LowerCaseEqualsLiteral("off"))
if (!form || !autocomplete.LowerCaseEqualsLiteral("off") || isPwmgrInput)
StartControllingInput(input);
}