Bug 1119063 - Don't autofill password fields with autocomplete=new-password. r=MattN

* Add form autofill outcome AUTOFILL_RESULT.PASSWORD_AUTOCOMPLETE_NEW_PASSWORD
* Autocomplete behavior is not changed

Differential Revision: https://phabricator.services.mozilla.com/D21274

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Sam Foster 2019-02-28 21:24:33 +00:00
Родитель 0f9b9dfe9d
Коммит a7e42bf6bd
3 изменённых файлов: 122 добавлений и 0 удалений

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

@ -1106,6 +1106,7 @@ var LoginManagerContent = {
* @param {bool} [options.userTriggered = false] an indication of whether
* this filling was triggered by the user
*/
// eslint-disable-next-line complexity
_fillForm(form, foundLogins, recipes, {
inputElement = null,
autofillForm = false,
@ -1133,6 +1134,7 @@ var LoginManagerContent = {
NO_AUTOFILL_FORMS: 8,
AUTOCOMPLETE_OFF: 9,
INSECURE: 10,
PASSWORD_AUTOCOMPLETE_NEW_PASSWORD: 11,
};
try {
@ -1247,6 +1249,14 @@ var LoginManagerContent = {
return;
}
// 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") {
log("not filling form, password field has the autocomplete new-password value");
autofillResult = AUTOFILL_RESULT.PASSWORD_AUTOCOMPLETE_NEW_PASSWORD;
return;
}
// Don't clobber an existing password.
if (passwordField.value && !clobberPassword) {
log("form not filled, the password field was already filled");

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

@ -21,6 +21,8 @@ support-files =
../authenticate.sjs
skip-if = toolkit == 'android' && !is_fennec # Don't run on GeckoView
# Note: new tests should use scheme = https unless they have a specific reason not to
[test_autocomplete_highlight.html]
scheme = https
skip-if = toolkit == 'android' # autocomplete
@ -82,6 +84,9 @@ support-files =
chrome_timeout.js
subtst_master_pass.html
[test_maxlength.html]
[test_autocomplete_new_password.html]
scheme = https
skip-if = toolkit == 'android' # autocomplete
[test_onsubmit_value_change.html]
[test_passwords_in_type_password.html]
[test_prompt.html]

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

@ -0,0 +1,107 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test autofill with autocomplete=new-password fields</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="pwmgr_common.js"></script>
<script type="text/javascript" src="../../../satchel/test/satchel_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
Login Manager test: autofill with autocomplete=new-password fields
<script>
let chromeScript = runInParent(function initLogins() {
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
let login1 = Cc["@mozilla.org/login-manager/loginInfo;1"]
.createInstance(Ci.nsILoginInfo);
login1.init("https://example.com", "https://autofill", null,
"user1", "pass1", "", "");
Services.logins.addLogin(login1);
});
let readyPromise = registerRunTests();
</script>
<p id="display"></p>
<!-- we presumably can't hide the content for this test. -->
<div id="content">
<!-- form1 is the reference, sanity-check -->
<form id="form1" action="https://autofill" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="p">
<button type="submit">Submit</button>
</form>
<!-- form2 uses the new-password field -->
<form id="form2" action="https://autofill" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" autocomplete="new-password">
<button type="submit">Submit</button>
</form>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
const {ContentTaskUtils} =
SpecialPowers.Cu.import("resource://testing-common/ContentTaskUtils.jsm", {});
async function getAutocompleteResult(input, expectedValues) {
input.focus();
const shownPromise = promiseACShown();
synthesizeKey("KEY_ArrowDown");
await shownPromise;
synthesizeKey("KEY_ArrowDown");
await synthesizeKey("KEY_Enter");
let didAutocomplete;
try {
await ContentTaskUtils.waitForCondition(() => {
for (let [selector, expectedValue] of Object.entries(expectedValues)) {
if (document.querySelector(selector).value !== expectedValue) {
return false;
}
}
return true;
});
didAutocomplete = true;
} catch (ex) {
info("waitForCondition exception: " + ex.message);
didAutocomplete = false;
}
return didAutocomplete;
}
add_task(async function setup() {
ok(readyPromise, "check promise is available");
await readyPromise;
});
add_task(async function test_autofillAutocompleteNewPassword() {
// reference form was filled as expected?
checkForm(1, "user1", "pass1");
// 2nd form should not be filled
checkForm(2, "", "");
let form = document.getElementById("form2");
let userInput = form.querySelector("[name='uname']");
const didAutocomplete = await getAutocompleteResult(userInput, {
"#form2 [name='uname']": "user1",
"#form2 [type='password']": "pass1",
});
ok(didAutocomplete, "Autocomplete of user and password fields should happen");
});
</script>
</pre>
</body>
</html>