зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1531135 - Honor autocomplete=off on password when signon.autofillForms.autocompleteOff is false. r=MattN
Differential Revision: https://phabricator.services.mozilla.com/D22025 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
07a1cbed27
Коммит
3528b01310
|
@ -4675,6 +4675,7 @@ pref("font.name-list.monospace.x-unicode", "dt-interface user-ucs2.cjk_japan-0")
|
|||
pref("signon.rememberSignons", true);
|
||||
pref("signon.rememberSignons.visibilityToggle", true);
|
||||
pref("signon.autofillForms", true);
|
||||
pref("signon.autofillForms.autocompleteOff", true);
|
||||
pref("signon.autofillForms.http", false);
|
||||
pref("signon.autologin.proxy", false);
|
||||
pref("signon.formlessCapture.enabled", true);
|
||||
|
|
|
@ -40,6 +40,7 @@ var LoginHelper = {
|
|||
|
||||
updateSignonPrefs() {
|
||||
this.autofillForms = Services.prefs.getBoolPref("signon.autofillForms");
|
||||
this.autofillAutocompleteOff = Services.prefs.getBoolPref("signon.autofillForms.autocompleteOff");
|
||||
this.debug = Services.prefs.getBoolPref("signon.debug");
|
||||
this.enabled = Services.prefs.getBoolPref("signon.rememberSignons");
|
||||
this.formlessCaptureEnabled = Services.prefs.getBoolPref("signon.formlessCapture.enabled");
|
||||
|
|
|
@ -1122,7 +1122,6 @@ var LoginManagerContent = {
|
|||
}
|
||||
|
||||
log("_fillForm", form.elements);
|
||||
let ignoreAutocomplete = true;
|
||||
// Will be set to one of AUTOFILL_RESULT in the `try` block.
|
||||
let autofillResult = -1;
|
||||
const AUTOFILL_RESULT = {
|
||||
|
@ -1214,13 +1213,6 @@ var LoginManagerContent = {
|
|||
return;
|
||||
}
|
||||
|
||||
var isAutocompleteOff = false;
|
||||
if (this._isAutocompleteDisabled(form) ||
|
||||
this._isAutocompleteDisabled(usernameField) ||
|
||||
this._isAutocompleteDisabled(passwordField)) {
|
||||
isAutocompleteOff = true;
|
||||
}
|
||||
|
||||
// Discard logins which have username/password values that don't
|
||||
// fit into the fields (as specified by the maxlength attribute).
|
||||
// The user couldn't enter these values anyway, and it helps
|
||||
|
@ -1252,9 +1244,11 @@ var LoginManagerContent = {
|
|||
return;
|
||||
}
|
||||
|
||||
const passwordACFieldName = passwordField.getAutocompleteInfo().fieldName;
|
||||
|
||||
// If the password field has the autocomplete value of "new-password"
|
||||
// and we're autofilling without user interaction, there's nothing to do.
|
||||
if (!userTriggered && passwordField.getAutocompleteInfo().fieldName == "new-password") {
|
||||
if (!userTriggered && passwordACFieldName == "new-password") {
|
||||
log("not filling form, password field has the autocomplete new-password value");
|
||||
autofillResult = AUTOFILL_RESULT.PASSWORD_AUTOCOMPLETE_NEW_PASSWORD;
|
||||
return;
|
||||
|
@ -1325,8 +1319,8 @@ var LoginManagerContent = {
|
|||
return;
|
||||
}
|
||||
|
||||
if (isAutocompleteOff && !ignoreAutocomplete) {
|
||||
log("Not filling the login because we're respecting autocomplete=off");
|
||||
if (!userTriggered && passwordACFieldName == "off" && !LoginHelper.autofillAutocompleteOff) {
|
||||
log("Not autofilling the login because we're respecting autocomplete=off");
|
||||
autofillResult = AUTOFILL_RESULT.AUTOCOMPLETE_OFF;
|
||||
return;
|
||||
}
|
||||
|
@ -1334,7 +1328,7 @@ var LoginManagerContent = {
|
|||
// Fill the form
|
||||
|
||||
if (usernameField) {
|
||||
// Don't modify the username field if it's disabled or readOnly so we preserve its case.
|
||||
// Don't modify the username field if it's disabled or readOnly so we preserve its case.
|
||||
let disabledOrReadOnly = usernameField.disabled || usernameField.readOnly;
|
||||
|
||||
let userNameDiffers = selectedLogin.username != usernameField.value;
|
||||
|
|
|
@ -51,6 +51,9 @@ skip-if = toolkit == 'android' # autocomplete
|
|||
[test_basic_form_3pw_1.html]
|
||||
[test_basic_form_autocomplete.html]
|
||||
skip-if = toolkit == 'android' # android:autocomplete.
|
||||
[test_basic_form_honor_autocomplete_off.html]
|
||||
scheme = https
|
||||
skip-if = toolkit == 'android' # android:autocomplete.
|
||||
[test_insecure_form_field_autocomplete.html]
|
||||
skip-if = toolkit == 'android' || os == 'linux' # android:autocomplete., linux: bug 1325778
|
||||
[test_password_field_autocomplete.html]
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test login autofill autocomplete when signon.autofillForms.autocompleteOff is false</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
|
||||
<script type="text/javascript" src="../../../satchel/test/satchel_common.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Login Manager test: autofilling when autocomplete=off
|
||||
|
||||
<script>
|
||||
let readyPromise = registerRunTests();
|
||||
|
||||
runInParent(function setup() {
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// Create some logins just for this form, since we'll be deleting them.
|
||||
const nsLoginInfo = Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
|
||||
Ci.nsILoginInfo, "init");
|
||||
assert.ok(nsLoginInfo != null, "nsLoginInfo constructor");
|
||||
|
||||
const login = new nsLoginInfo("https://example.com", "https://autocomplete2", null,
|
||||
"singleuser", "singlepass", "uname", "pword");
|
||||
Services.logins.addLogin(login);
|
||||
});
|
||||
</script>
|
||||
<p id="display"></p>
|
||||
|
||||
<!-- we presumably can't hide the content for this test. -->
|
||||
<div id="content">
|
||||
<!-- test single logins, with autocomplete=off set -->
|
||||
<form id="form1" action="https://autocomplete2" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword" autocomplete="off">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<form id="form2" action="https://autocomplete2" onsubmit="return false;">
|
||||
<input type="text" name="uname" autocomplete="off">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<form id="form3" action="https://autocomplete2" onsubmit="return false;" autocomplete="off">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<form id="form4" action="https://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="form5" action="https://autocomplete2" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
/** Test for Login Manager: multiple login autocomplete. **/
|
||||
let {ContentTaskUtils} = SpecialPowers.Cu.import("resource://testing-common/ContentTaskUtils.jsm", {});
|
||||
|
||||
// Set the pref before the document loads.
|
||||
SpecialPowers.setBoolPref("signon.autofillForms.autocompleteOff", false);
|
||||
|
||||
SimpleTest.registerCleanupFunction(() => {
|
||||
SpecialPowers.clearUserPref("signon.autofillForms.autocompleteOff");
|
||||
});
|
||||
|
||||
// Check for expected username/password in form.
|
||||
function checkFormValues(form, expectedUsername, expectedPassword) {
|
||||
let uname = form.querySelector("[name='uname']");
|
||||
let pword = form.querySelector("[name='pword']");
|
||||
is(uname.value, expectedUsername, `Checking ${form.id} username is: ${expectedUsername}`);
|
||||
is(pword.value, expectedPassword, `Checking ${form.id} password is: ${expectedPassword}`);
|
||||
}
|
||||
|
||||
async function autoCompleteFieldsFromFirstMatch(form) {
|
||||
// trigger autocomplete from the username field
|
||||
await SimpleTest.promiseFocus(form.ownerGlobal);
|
||||
let uname = form.querySelector("[name='uname']");
|
||||
let shownPromise = promiseACShown();
|
||||
uname.focus();
|
||||
await shownPromise;
|
||||
|
||||
let formFilled = promiseFormsProcessed();
|
||||
await synthesizeKey("KEY_ArrowDown"); // open
|
||||
await synthesizeKey("KEY_Enter");
|
||||
await formFilled;
|
||||
await Promise.resolve();
|
||||
}
|
||||
|
||||
add_task(async function setup() {
|
||||
ok(readyPromise, "check promise is available");
|
||||
await readyPromise;
|
||||
listenForUnexpectedPopupShown();
|
||||
});
|
||||
|
||||
/* Tests for autofill of single-user forms for when we honor autocomplete=off on password fields */
|
||||
add_task(async function test_form1_honor_password_autocomplete_off() {
|
||||
await SimpleTest.promiseFocus(window);
|
||||
// With the pref toggled off, and with autocomplete=off on the password field,
|
||||
// we expect not to have autofilled this form
|
||||
let form = document.getElementById("form1");
|
||||
ok(form, "found form under test");
|
||||
checkFormValues(form, "", "");
|
||||
|
||||
// ..but it should autocomplete just fine
|
||||
await autoCompleteFieldsFromFirstMatch(form);
|
||||
checkFormValues(form, "singleuser", "singlepass");
|
||||
});
|
||||
|
||||
add_task(async function test_form2_honor_password_autocomplete_off() {
|
||||
await SimpleTest.promiseFocus(window);
|
||||
// With the pref toggled off, and with autocomplete=off on the username field,
|
||||
// we expect to have autofilled this form
|
||||
let form = document.getElementById("form2");
|
||||
ok(form, "found form under test");
|
||||
checkFormValues(form, "singleuser", "singlepass");
|
||||
});
|
||||
|
||||
add_task(async function test_form3_honor_password_autocomplete_off() {
|
||||
await SimpleTest.promiseFocus(window);
|
||||
// With the pref toggled off, and with autocomplete=off on the form,
|
||||
// we expect to have autofilled this form
|
||||
let form = document.getElementById("form3");
|
||||
ok(form, "found form under test");
|
||||
checkFormValues(form, "singleuser", "singlepass");
|
||||
});
|
||||
|
||||
add_task(async function test_form4_honor_password_autocomplete_off() {
|
||||
await SimpleTest.promiseFocus(window);
|
||||
// With the pref toggled off, and autocomplete=off on the username and password field,
|
||||
// we expect not to have autofilled this form
|
||||
let form = document.getElementById("form4");
|
||||
ok(form, "found form under test");
|
||||
checkFormValues(form, "", "");
|
||||
|
||||
// ..but it should autocomplete just fine
|
||||
await autoCompleteFieldsFromFirstMatch(form);
|
||||
checkFormValues(form, "singleuser", "singlepass");
|
||||
});
|
||||
|
||||
add_task(async function test_form5() {
|
||||
await SimpleTest.promiseFocus(window);
|
||||
// (this is a control, w/o autocomplete=off, to ensure the login
|
||||
// that was being suppressed would have been filled in otherwise)
|
||||
let form = document.getElementById("form5");
|
||||
ok(form, "found form under test");
|
||||
checkFormValues(form, "singleuser", "singlepass");
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче