Bug 1569989 - Show the password visibility toggle in some dismissed-by-default doorhangers. r=sfoster

If the login is older than 2 minutes, don't allow revealing the password in the doorhanger.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Matthew Noorenberghe 2019-08-09 02:22:18 +00:00
Родитель d2cebb5e64
Коммит 1765f44b34
4 изменённых файлов: 148 добавлений и 18 удалений

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

@ -863,7 +863,7 @@ this.LoginManagerParent = {
prompter.promptToChangePassword(
loginToChange,
formLogin,
true, // dimissed prompt
true, // dismissed prompt
autoSaveLogin // notifySaved
);
return;
@ -871,7 +871,7 @@ this.LoginManagerParent = {
log("_onGeneratedPasswordFilledOrEdited: no matching login to save/update");
prompter.promptToSavePassword(
formLogin,
true, // dimissed prompt
true, // dismissed prompt
autoSaveLogin // notifySaved
);
},

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

@ -29,6 +29,13 @@ const LoginInfo = Components.Constructor(
const BRAND_BUNDLE = "chrome://branding/locale/brand.properties";
/**
* The maximum age of the password in ms (using `timePasswordChanged`) whereby
* a user can toggle the password visibility in a doorhanger to add a username to
* a saved login.
*/
const VISIBILITY_TOGGLE_MAX_PW_AGE_MS = 2 * 60 * 1000; // 2 minutes
/**
* Constants for password prompt telemetry.
* Mirrored in mobile/android/components/LoginManagerPrompter.js */
@ -1274,15 +1281,18 @@ LoginManagerPrompter.prototype = {
toggleBtn.addEventListener("command", onVisibilityToggle);
toggleBtn.setAttribute("label", togglePasswordLabel);
toggleBtn.setAttribute("accesskey", togglePasswordAccessKey);
toggleBtn.setAttribute(
"hidden",
LoginHelper.isMasterPasswordSet()
);
}
if (this.wasDismissed) {
chromeDoc
.getElementById("password-notification-visibilityToggle")
.setAttribute("hidden", true);
let hideToggle =
LoginHelper.isMasterPasswordSet() ||
// Dismissed-by-default prompts should still show the toggle.
(this.timeShown && this.wasDismissed) ||
// If we are only adding a username then the password is
// one that is already saved and we don't want to reveal
// it as the submitter of this form may not be the account
// owner, they may just be using the saved password.
(messageStringID == "updateLoginMsgAddUsername" &&
login.timePasswordChanged <
Date.now() - VISIBILITY_TOGGLE_MAX_PW_AGE_MS);
toggleBtn.setAttribute("hidden", hideToggle);
}
break;
case "shown": {

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

@ -303,11 +303,11 @@ add_task(async function test_noPasswordField() {
);
});
add_task(async function test_pwOnlyLoginMatchesForm() {
info("Check for update popup when existing pw-only login matches form.");
add_task(async function test_pwOnlyNewLoginMatchesUPForm() {
info("Check for update popup when new existing pw-only login matches form.");
Services.logins.addLogin(login2);
await testSubmittingLoginForm("subtst_notifications_1.html", function(
await testSubmittingLoginForm("subtst_notifications_1.html", async function(
fieldValues
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
@ -319,17 +319,81 @@ add_task(async function test_pwOnlyLoginMatchesForm() {
"Would you like to add a username to the saved password?",
"Check message"
);
notif.remove();
let { panel } = PopupNotifications;
let passwordVisiblityToggle = panel.querySelector(
"#password-notification-visibilityToggle"
);
ok(
!passwordVisiblityToggle.hidden,
"Toggle visible for a recently saved pw"
);
await checkDoorhangerUsernamePassword("notifyu1", "notifyp1");
clickDoorhangerButton(notif, CHANGE_BUTTON);
ok(!getCaptureDoorhanger("password-change"), "popup should be gone");
});
let logins = Services.logins.getAllLogins();
is(logins.length, 1, "Should only have 1 login");
let login = logins[0].QueryInterface(Ci.nsILoginMetaInfo);
is(login.username, "", "Check the username");
is(login.username, "notifyu1", "Check the username");
is(login.password, "notifyp1", "Check the password");
is(login.timesUsed, 1, "Check times used");
is(login.timesUsed, 2, "Check times used");
Services.logins.removeLogin(login2);
Services.logins.removeLogin(login);
});
add_task(async function test_pwOnlyOldLoginMatchesUPForm() {
info("Check for update popup when old existing pw-only login matches form.");
Services.logins.addLogin(login2);
// Change the timePasswordChanged to be old so that the password won't be
// revealed in the doorhanger.
let oldTimeMS = new Date("2009-11-15").getTime();
Services.logins.modifyLogin(
login2,
LoginHelper.newPropertyBag({
timeCreated: oldTimeMS,
timeLastUsed: oldTimeMS + 1,
timePasswordChanged: oldTimeMS,
})
);
await testSubmittingLoginForm("subtst_notifications_1.html", async function(
fieldValues
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = getCaptureDoorhanger("password-change");
ok(notif, "checking for notification popup");
is(
notif.message,
"Would you like to add a username to the saved password?",
"Check message"
);
let { panel } = PopupNotifications;
let passwordVisiblityToggle = panel.querySelector(
"#password-notification-visibilityToggle"
);
ok(passwordVisiblityToggle.hidden, "Toggle hidden for an old saved pw");
await checkDoorhangerUsernamePassword("notifyu1", "notifyp1");
clickDoorhangerButton(notif, CHANGE_BUTTON);
ok(!getCaptureDoorhanger("password-change"), "popup should be gone");
});
let logins = Services.logins.getAllLogins();
is(logins.length, 1, "Should only have 1 login");
let login = logins[0].QueryInterface(Ci.nsILoginMetaInfo);
is(login.username, "notifyu1", "Check the username");
is(login.password, "notifyp1", "Check the password");
is(login.timesUsed, 2, "Check times used");
Services.logins.removeLogin(login);
});
add_task(async function test_pwOnlyFormMatchesLogin() {
@ -787,5 +851,36 @@ add_task(async function test_noShowPasswordOnDismissal() {
});
});
add_task(async function test_showPasswordOn1stOpenOfDismissedByDefault() {
info("Show Password toggle when the doorhanger is dismissed by default");
await testSubmittingLoginForm("subtst_notifications_1.html", async function(
fieldValues
) {
info("Opening popup");
let notif = getCaptureDoorhanger("password-save");
let { panel } = PopupNotifications;
info("Hiding popup.");
let promiseHidden = BrowserTestUtils.waitForEvent(panel, "popuphidden");
panel.hidePopup();
await promiseHidden;
info("Clicking on anchor to reshow popup.");
let promiseShown = BrowserTestUtils.waitForEvent(panel, "popupshown");
notif.anchorElement.click();
await promiseShown;
let passwordVisiblityToggle = panel.querySelector(
"#password-notification-visibilityToggle"
);
is(
passwordVisiblityToggle.hidden,
true,
"Check that the Show Password field is Hidden"
);
});
});
// TODO:
// * existing login test, form has different password --> change password, no save prompt

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

@ -234,6 +234,31 @@ add_task(async function test_private_popup_notification_2() {
() => notif.dismissed,
"notification should be dismissed"
);
let { panel } = privateWin.PopupNotifications;
let promiseShown = BrowserTestUtils.waitForEvent(panel, "popupshown");
notif.anchorElement.click();
await promiseShown;
let notificationElement = panel.childNodes[0];
let toggleCheckbox = notificationElement.querySelector(
"#password-notification-visibilityToggle"
);
ok(!toggleCheckbox.hidden, "Toggle should be visible upon 1st opening");
info("Hiding popup.");
let promiseHidden = BrowserTestUtils.waitForEvent(panel, "popuphidden");
panel.hidePopup();
await promiseHidden;
info("Clicking on anchor to reshow popup.");
promiseShown = BrowserTestUtils.waitForEvent(panel, "popupshown");
notif.anchorElement.click();
await promiseShown;
ok(toggleCheckbox.hidden, "Toggle should be hidden upon 2nd opening");
notif.remove();
}
}