зеркало из 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", true);
|
||||||
pref("signon.rememberSignons.visibilityToggle", true);
|
pref("signon.rememberSignons.visibilityToggle", true);
|
||||||
pref("signon.autofillForms", true);
|
pref("signon.autofillForms", true);
|
||||||
|
pref("signon.autofillForms.autocompleteOff", true);
|
||||||
pref("signon.autofillForms.http", false);
|
pref("signon.autofillForms.http", false);
|
||||||
pref("signon.autologin.proxy", false);
|
pref("signon.autologin.proxy", false);
|
||||||
pref("signon.formlessCapture.enabled", true);
|
pref("signon.formlessCapture.enabled", true);
|
||||||
|
|
|
@ -40,6 +40,7 @@ var LoginHelper = {
|
||||||
|
|
||||||
updateSignonPrefs() {
|
updateSignonPrefs() {
|
||||||
this.autofillForms = Services.prefs.getBoolPref("signon.autofillForms");
|
this.autofillForms = Services.prefs.getBoolPref("signon.autofillForms");
|
||||||
|
this.autofillAutocompleteOff = Services.prefs.getBoolPref("signon.autofillForms.autocompleteOff");
|
||||||
this.debug = Services.prefs.getBoolPref("signon.debug");
|
this.debug = Services.prefs.getBoolPref("signon.debug");
|
||||||
this.enabled = Services.prefs.getBoolPref("signon.rememberSignons");
|
this.enabled = Services.prefs.getBoolPref("signon.rememberSignons");
|
||||||
this.formlessCaptureEnabled = Services.prefs.getBoolPref("signon.formlessCapture.enabled");
|
this.formlessCaptureEnabled = Services.prefs.getBoolPref("signon.formlessCapture.enabled");
|
||||||
|
|
|
@ -1122,7 +1122,6 @@ var LoginManagerContent = {
|
||||||
}
|
}
|
||||||
|
|
||||||
log("_fillForm", form.elements);
|
log("_fillForm", form.elements);
|
||||||
let ignoreAutocomplete = true;
|
|
||||||
// Will be set to one of AUTOFILL_RESULT in the `try` block.
|
// Will be set to one of AUTOFILL_RESULT in the `try` block.
|
||||||
let autofillResult = -1;
|
let autofillResult = -1;
|
||||||
const AUTOFILL_RESULT = {
|
const AUTOFILL_RESULT = {
|
||||||
|
@ -1214,13 +1213,6 @@ var LoginManagerContent = {
|
||||||
return;
|
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
|
// Discard logins which have username/password values that don't
|
||||||
// fit into the fields (as specified by the maxlength attribute).
|
// fit into the fields (as specified by the maxlength attribute).
|
||||||
// The user couldn't enter these values anyway, and it helps
|
// The user couldn't enter these values anyway, and it helps
|
||||||
|
@ -1252,9 +1244,11 @@ var LoginManagerContent = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const passwordACFieldName = passwordField.getAutocompleteInfo().fieldName;
|
||||||
|
|
||||||
// If the password field has the autocomplete value of "new-password"
|
// If the password field has the autocomplete value of "new-password"
|
||||||
// and we're autofilling without user interaction, there's nothing to do.
|
// 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");
|
log("not filling form, password field has the autocomplete new-password value");
|
||||||
autofillResult = AUTOFILL_RESULT.PASSWORD_AUTOCOMPLETE_NEW_PASSWORD;
|
autofillResult = AUTOFILL_RESULT.PASSWORD_AUTOCOMPLETE_NEW_PASSWORD;
|
||||||
return;
|
return;
|
||||||
|
@ -1325,8 +1319,8 @@ var LoginManagerContent = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAutocompleteOff && !ignoreAutocomplete) {
|
if (!userTriggered && passwordACFieldName == "off" && !LoginHelper.autofillAutocompleteOff) {
|
||||||
log("Not filling the login because we're respecting autocomplete=off");
|
log("Not autofilling the login because we're respecting autocomplete=off");
|
||||||
autofillResult = AUTOFILL_RESULT.AUTOCOMPLETE_OFF;
|
autofillResult = AUTOFILL_RESULT.AUTOCOMPLETE_OFF;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,9 @@ skip-if = toolkit == 'android' # autocomplete
|
||||||
[test_basic_form_3pw_1.html]
|
[test_basic_form_3pw_1.html]
|
||||||
[test_basic_form_autocomplete.html]
|
[test_basic_form_autocomplete.html]
|
||||||
skip-if = toolkit == 'android' # android:autocomplete.
|
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]
|
[test_insecure_form_field_autocomplete.html]
|
||||||
skip-if = toolkit == 'android' || os == 'linux' # android:autocomplete., linux: bug 1325778
|
skip-if = toolkit == 'android' || os == 'linux' # android:autocomplete., linux: bug 1325778
|
||||||
[test_password_field_autocomplete.html]
|
[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>
|
Загрузка…
Ссылка в новой задаче