Backed out 3 changesets (bug 1560042) for causing browser-chrome failures on browser_temporary_permissions.js CLOSED TREEE

Backed out changeset 0fb712c93395 (bug 1560042)
Backed out changeset ada7b53d87d6 (bug 1560042)
Backed out changeset cdae11ea2306 (bug 1560042)
This commit is contained in:
arthur.iakab 2019-08-20 04:04:18 +03:00
parent 12ea9cfff0
commit 1d06495330
16 changed files with 325 additions and 1445 deletions

View File

@ -570,19 +570,19 @@ this.LoginManagerParent = {
formActionOrigin,
});
let { browsingContext } = browser;
let framePrincipalOrigin =
browsingContext.currentWindowGlobal.documentPrincipal.origin;
let generatedPW = this._generatedPasswordsByPrincipalOrigin.get(
framePrincipalOrigin
);
// If we didn't find a username field, but seem to be changing a
// password, allow the user to select from a list of applicable
// logins to update the password for.
if (!usernameField && oldPasswordField && logins.length > 0) {
let prompter = this._getPrompter(browser, openerTopWindowID);
let { browsingContext } = browser;
let framePrincipalOrigin =
browsingContext.currentWindowGlobal.documentPrincipal.origin;
let generatedPW = this._generatedPasswordsByPrincipalOrigin.get(
framePrincipalOrigin
);
if (logins.length == 1) {
let oldLogin = logins[0];
@ -595,25 +595,10 @@ this.LoginManagerParent = {
return;
}
let autoSavedStorageGUID = "";
if (
generatedPW &&
generatedPW.storageGUID == oldLogin.guid &&
generatedPW.value == formLogin.password
) {
// this login has a generated password, auto-saved in this session
autoSavedStorageGUID = generatedPW.storageGUID;
}
formLogin.username = oldLogin.username;
formLogin.usernameField = oldLogin.usernameField;
prompter.promptToChangePassword(
oldLogin,
formLogin,
dismissedPrompt,
false, // notifySaved
autoSavedStorageGUID
);
prompter.promptToChangePassword(oldLogin, formLogin, dismissedPrompt);
return;
} else if (!generatedPW || generatedPW.value != newPasswordField.value) {
// Note: It's possible that that we already have the correct u+p saved
@ -663,15 +648,6 @@ this.LoginManagerParent = {
if (existingLogin) {
log("Found an existing login matching this form submission");
let autoSavedStorageGUID = "";
if (
generatedPW &&
generatedPW.storageGUID == existingLogin.guid &&
generatedPW.value == formLogin.password
) {
// this login has a generated password, auto-saved in this session
autoSavedStorageGUID = generatedPW.storageGUID;
}
// Change password if needed.
if (existingLogin.password != formLogin.password) {
@ -680,9 +656,7 @@ this.LoginManagerParent = {
prompter.promptToChangePassword(
existingLogin,
formLogin,
dismissedPrompt,
false, // notifySaved
autoSavedStorageGUID
dismissedPrompt
);
} else if (!existingLogin.username && formLogin.username) {
log("...empty username update, prompting to change.");
@ -690,9 +664,7 @@ this.LoginManagerParent = {
prompter.promptToChangePassword(
existingLogin,
formLogin,
dismissedPrompt,
false, // notifySaved
autoSavedStorageGUID
dismissedPrompt
);
} else {
recordLoginUse(existingLogin);
@ -888,24 +860,11 @@ this.LoginManagerParent = {
if (loginToChange) {
// Show a change doorhanger to allow modifying an already-saved login
// e.g. to add a username or update the password.
let autoSavedStorageGUID = "";
if (
generatedPW.value == loginToChange.password &&
generatedPW.storageGUID == loginToChange.guid
) {
autoSavedStorageGUID = generatedPW.storageGUID;
}
log(
"_onGeneratedPasswordFilledOrEdited: promptToChangePassword with autoSavedStorageGUID: " +
autoSavedStorageGUID
);
prompter.promptToChangePassword(
loginToChange,
formLogin,
true, // dismissed prompt
autoSaveLogin, // notifySaved
autoSavedStorageGUID // autoSavedLoginGuid
autoSaveLogin // notifySaved
);
return;
}

View File

@ -958,7 +958,7 @@ LoginManagerPrompter.prototype = {
*
* @param {nsILoginInfo} login
* Login to save or change. For changes, this login should contain the
* new password and/or username
* new password.
* @param {string} type
* This is "password-save" or "password-change" depending on the
* original notification type. This is used for telemetry and tests.
@ -968,23 +968,17 @@ LoginManagerPrompter.prototype = {
* Whether to indicate to the user that the login was already saved.
* @param {string} [options.messageStringID = undefined]
* An optional string ID to override the default message.
* @param {string} [options.autoSavedLoginGuid = ""]
* A string guid value for the old login to be removed if the changes
* match it to an different login
*/
_showLoginCaptureDoorhanger(
login,
type,
showOptions = {},
{ notifySaved = false, messageStringID, autoSavedLoginGuid = "" } = {}
{ notifySaved = false, messageStringID } = {}
) {
let { browser } = this._getNotifyWindow();
if (!browser) {
return;
}
this.log(
`_showLoginCaptureDoorhanger, got autoSavedLoginGuid: ${autoSavedLoginGuid}`
);
let saveMsgNames = {
prompt: login.username === "" ? "saveLoginMsgNoUser" : "saveLoginMsg",
@ -1050,9 +1044,6 @@ LoginManagerPrompter.prototype = {
};
let updateButtonLabel = () => {
if (!currentNotification) {
Cu.reportError("updateButtonLabel, no currentNotification");
}
let foundLogins = LoginHelper.searchLoginsWithObject({
formActionOrigin: login.formActionOrigin,
origin: login.origin,
@ -1060,11 +1051,7 @@ LoginManagerPrompter.prototype = {
schemeUpgrades: LoginHelper.schemeUpgrades,
});
let logins = this._filterUpdatableLogins(
login,
foundLogins,
autoSavedLoginGuid
);
let logins = this._filterUpdatableLogins(login, foundLogins);
let msgNames = logins.length == 0 ? saveMsgNames : changeMsgNames;
// Update the label based on whether this will be a new login or not.
@ -1152,11 +1139,7 @@ LoginManagerPrompter.prototype = {
schemeUpgrades: LoginHelper.schemeUpgrades,
});
let logins = this._filterUpdatableLogins(
login,
foundLogins,
autoSavedLoginGuid
);
let logins = this._filterUpdatableLogins(login, foundLogins);
let resolveBy = ["scheme", "timePasswordChanged"];
logins = LoginHelper.dedupeLogins(
logins,
@ -1164,28 +1147,8 @@ LoginManagerPrompter.prototype = {
resolveBy,
login.origin
);
// sort exact username matches to the top
logins.sort(l => (l.username == login.username ? -1 : 1));
this.log(`persistData: Matched ${logins.length} logins`);
let loginToRemove;
let loginToUpdate = logins.shift();
if (logins.length && logins[0].guid == autoSavedLoginGuid) {
loginToRemove = logins.shift();
}
if (logins.length) {
this.log(
"multiple logins, loginToRemove:",
loginToRemove && loginToRemove.guid
);
Cu.reportError("Unexpected match of multiple logins.");
return;
}
if (!loginToUpdate) {
// Create a new login, don't update an original.
if (logins.length == 0) {
// The original login we have been provided with might have its own
// metadata, but we don't want it propagated to the newly created one.
Services.logins.addLogin(
@ -1199,21 +1162,18 @@ LoginManagerPrompter.prototype = {
login.passwordField
)
);
} else if (
loginToUpdate.password == login.password &&
loginToUpdate.username == login.username
) {
// We only want to touch the login's use count and last used time.
this.log("persistData: Touch matched login", loginToUpdate.guid);
this._updateLogin(loginToUpdate);
} else if (logins.length == 1) {
if (
logins[0].password == login.password &&
logins[0].username == login.username
) {
// We only want to touch the login's use count and last used time.
this._updateLogin(logins[0]);
} else {
this._updateLogin(logins[0], login);
}
} else {
this.log("persistData: Update matched login", loginToUpdate.guid);
this._updateLogin(loginToUpdate, login);
}
if (loginToRemove) {
this.log("persistData: removing login", loginToRemove.guid);
Services.logins.removeLogin(loginToRemove);
Cu.reportError("Unexpected match of multiple logins.");
}
};
@ -1454,21 +1414,15 @@ LoginManagerPrompter.prototype = {
* The old login we may want to update.
* @param {nsILoginInfo} aNewLogin
* The new login from the page form.
* @param {boolean} [dismissed = false]
* If the prompt should be automatically dismissed on being shown.
* @param {boolean} [notifySaved = false]
* Whether the notification should indicate that a login has been saved
* @param {string} [autoSavedLoginGuid = ""]
* A guid value for the old login to be removed if the changes match it
* to a different login
* @param dismissed
* A boolean indicating if the prompt should be automatically
* dismissed on being shown.
* @param notifySaved
* A boolean value indicating whether the notification should indicate that
* a login has been saved
*/
promptToChangePassword(
aOldLogin,
aNewLogin,
dismissed = false,
notifySaved = false,
autoSavedLoginGuid = ""
) {
promptToChangePassword(aOldLogin, aNewLogin, dismissed, notifySaved) {
this.log("promptToChangePassword");
let notifyObj = this._getPopupNote();
if (notifyObj) {
@ -1477,8 +1431,7 @@ LoginManagerPrompter.prototype = {
aOldLogin,
aNewLogin,
dismissed,
notifySaved,
autoSavedLoginGuid
notifySaved
);
} else {
this._showChangeLoginDialog(aOldLogin, aNewLogin);
@ -1508,8 +1461,7 @@ LoginManagerPrompter.prototype = {
aOldLogin,
aNewLogin,
dismissed = false,
notifySaved = false,
autoSavedLoginGuid = ""
notifySaved = false
) {
let login = aOldLogin.clone();
login.origin = aNewLogin.origin;
@ -1539,7 +1491,6 @@ LoginManagerPrompter.prototype = {
{
notifySaved,
messageStringID,
autoSavedLoginGuid,
}
);
@ -1931,26 +1882,21 @@ LoginManagerPrompter.prototype = {
* to match a submitted login, instead of creating a new one.
*
* Given a login and a loginList, it filters the login list
* to find every login with either:
* - the same username as aLogin
* - the same password as aLogin and an empty username
* so the user can add a username.
* - the same guid as the given login when it has an empty username
* to find every login with either the same username as aLogin
* or with the same password as aLogin and an empty username
* so the user can add a username.
*
* @param {nsILoginInfo} aLogin
* login to use as filter.
* @param {nsILoginInfo[]} aLoginList
* Array of logins to filter.
* @param {String} includeGUID
* guid value for login that not be filtered out
* @returns {nsILoginInfo[]} the filtered array of logins.
*/
_filterUpdatableLogins(aLogin, aLoginList, includeGUID) {
_filterUpdatableLogins(aLogin, aLoginList) {
return aLoginList.filter(
l =>
l.username == aLogin.username ||
(l.password == aLogin.password && !l.username) ||
(includeGUID && includeGUID == l.guid)
(l.password == aLogin.password && !l.username)
);
},
}; // end of LoginManagerPrompter implementation

View File

@ -71,15 +71,11 @@ interface nsILoginManagerPrompter : nsISupports {
* @param dismissed
* A boolean value indicating whether the save logins doorhanger should
* be dismissed automatically when shown.
* @param autoSavedLoginGuid
* A string guid value for the old login to be removed if the changes
* match it to a different login
*/
void promptToChangePassword(in nsILoginInfo aOldLogin,
in nsILoginInfo aNewLogin,
[optional] in boolean dismissed,
[optional] in boolean notifySaved,
[optional] in AString autoSavedLoginGuid);
[optional] in boolean notifySaved);
/**
* Ask the user if they want to change the password for one of

View File

@ -70,15 +70,8 @@ this.LoginTestUtils = {
(_, data) => data == "addLogin"
);
Services.logins.addLogin(login);
let [savedLogin] = await storageChangedPromised;
return savedLogin;
},
resetGeneratedPasswordsCache() {
let { LoginManagerParent } = ChromeUtils.import(
"resource://gre/modules/LoginManagerParent.jsm"
);
LoginManagerParent._generatedPasswordsByPrincipalOrigin.clear();
await storageChangedPromised;
return login;
},
/**

View File

@ -108,4 +108,3 @@ support-files =
subtst_privbrowsing_1.html
form_password_change.html
skip-if = fission
[browser_promptToChangePassword.js]

View File

@ -66,14 +66,14 @@ add_task(async function setup() {
});
add_task(async function test_remember_opens() {
await testSubmittingLoginForm("subtst_notifications_1.html", async function(
await testSubmittingLoginForm("subtst_notifications_1.html", function(
fieldValues
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
await cleanupDoorhanger(notif);
notif.remove();
});
});
@ -83,7 +83,7 @@ add_task(async function test_clickNever() {
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
is(
true,
@ -93,7 +93,6 @@ add_task(async function test_clickNever() {
await checkDoorhangerUsernamePassword("notifyu1", "notifyp1");
clickDoorhangerButton(notif, NEVER_MENUITEM);
await cleanupDoorhanger(notif);
});
is(
@ -131,7 +130,7 @@ add_task(async function test_clickRemember() {
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
is(
@ -179,7 +178,6 @@ add_task(async function test_clickRemember() {
// remove that login
Services.logins.removeLogin(login1);
await cleanupDoorhanger();
});
/* signons.rememberSignons pref tests... */
@ -208,14 +206,14 @@ add_task(async function test_rememberSignonsTrue() {
info("Make sure we prompt with rememberSignons=true");
Services.prefs.setBoolPref("signon.rememberSignons", true);
await testSubmittingLoginForm("subtst_notifications_1.html", async function(
await testSubmittingLoginForm("subtst_notifications_1.html", function(
fieldValues
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
await cleanupDoorhanger(notif);
notif.remove();
});
is(
@ -232,14 +230,14 @@ add_task(async function test_autocompleteOffUsername() {
"Check for notification popup when autocomplete=off present on username"
);
await testSubmittingLoginForm("subtst_notifications_2.html", async function(
await testSubmittingLoginForm("subtst_notifications_2.html", function(
fieldValues
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "checking for notification popup");
await cleanupDoorhanger(notif);
notif.remove();
});
is(
@ -254,14 +252,14 @@ add_task(async function test_autocompleteOffPassword() {
"Check for notification popup when autocomplete=off present on password"
);
await testSubmittingLoginForm("subtst_notifications_3.html", async function(
await testSubmittingLoginForm("subtst_notifications_3.html", function(
fieldValues
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "checking for notification popup");
await cleanupDoorhanger(notif);
notif.remove();
});
is(
@ -274,14 +272,14 @@ add_task(async function test_autocompleteOffPassword() {
add_task(async function test_autocompleteOffForm() {
info("Check for notification popup when autocomplete=off present on form");
await testSubmittingLoginForm("subtst_notifications_4.html", async function(
await testSubmittingLoginForm("subtst_notifications_4.html", function(
fieldValues
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "checking for notification popup");
await cleanupDoorhanger(notif);
notif.remove();
});
is(
@ -319,7 +317,7 @@ add_task(async function test_pwOnlyNewLoginMatchesUPForm() {
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-change");
let notif = getCaptureDoorhanger("password-change");
ok(notif, "checking for notification popup");
is(
notif.message,
@ -373,7 +371,7 @@ add_task(async function test_pwOnlyOldLoginMatchesUPForm() {
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-change");
let notif = getCaptureDoorhanger("password-change");
ok(notif, "checking for notification popup");
is(
notif.message,
@ -434,14 +432,14 @@ add_task(async function test_pwOnlyFormDoesntMatchExisting() {
);
Services.logins.addLogin(login1B);
await testSubmittingLoginForm("subtst_notifications_6.html", async function(
await testSubmittingLoginForm("subtst_notifications_6.html", function(
fieldValues
) {
is(fieldValues.username, "null", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
await cleanupDoorhanger(notif);
notif.remove();
});
let logins = Services.logins.getAllLogins();
@ -463,7 +461,7 @@ add_task(async function test_changeUPLoginOnUPForm_dont() {
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "pass2", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-change");
let notif = getCaptureDoorhanger("password-change");
ok(notif, "got notification popup");
is(notif.message, "Would you like to update this login?", "Check message");
@ -490,7 +488,7 @@ add_task(async function test_changeUPLoginOnUPForm_change() {
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "pass2", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-change");
let notif = getCaptureDoorhanger("password-change");
ok(notif, "got notification popup");
is(notif.message, "Would you like to update this login?", "Check message");
@ -524,7 +522,7 @@ add_task(async function test_changePLoginOnUPForm() {
) {
is(fieldValues.username, "", "Checking submitted username");
is(fieldValues.password, "pass2", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-change");
let notif = getCaptureDoorhanger("password-change");
ok(notif, "got notification popup");
is(notif.message, "Would you like to update this password?", "Check msg");
@ -552,7 +550,7 @@ add_task(async function test_changePLoginOnPForm() {
) {
is(fieldValues.username, "null", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-change");
let notif = getCaptureDoorhanger("password-change");
ok(notif, "got notification popup");
is(notif.message, "Would you like to update this password?", "Check msg");
@ -575,12 +573,12 @@ add_task(async function test_changePLoginOnPForm() {
add_task(async function test_checkUPSaveText() {
info("Check text on a user+pass notification popup");
await testSubmittingLoginForm("subtst_notifications_1.html", async function(
await testSubmittingLoginForm("subtst_notifications_1.html", function(
fieldValues
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
// Check the text, which comes from the localized saveLoginMsg string.
let notificationText = notif.message;
@ -589,7 +587,7 @@ add_task(async function test_checkUPSaveText() {
BRAND_SHORT_NAME +
" to save this login for example.com?";
is(expectedText, notificationText, "Checking text: " + notificationText);
await cleanupDoorhanger(notif);
notif.remove();
});
is(
@ -602,12 +600,12 @@ add_task(async function test_checkUPSaveText() {
add_task(async function test_checkPSaveText() {
info("Check text on a pass-only notification popup");
await testSubmittingLoginForm("subtst_notifications_6.html", async function(
await testSubmittingLoginForm("subtst_notifications_6.html", function(
fieldValues
) {
is(fieldValues.username, "null", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
// Check the text, which comes from the localized saveLoginMsgNoUser string.
let notificationText = notif.message;
@ -616,7 +614,7 @@ add_task(async function test_checkPSaveText() {
BRAND_SHORT_NAME +
" to save this password for example.com?";
is(expectedText, notificationText, "Checking text: " + notificationText);
await cleanupDoorhanger(notif);
notif.remove();
});
is(
@ -632,16 +630,15 @@ add_task(async function test_capture2pw0un() {
"is submitted and there are no saved logins."
);
await testSubmittingLoginForm(
"subtst_notifications_2pw_0un.html",
async function(fieldValues) {
is(fieldValues.username, "null", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
ok(notif, "got notification popup");
await cleanupDoorhanger(notif);
}
);
await testSubmittingLoginForm("subtst_notifications_2pw_0un.html", function(
fieldValues
) {
is(fieldValues.username, "null", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
notif.remove();
});
is(
Services.logins.getAllLogins().length,
@ -658,16 +655,15 @@ add_task(async function test_change2pw0unExistingDifferentUP() {
Services.logins.addLogin(login1B);
await testSubmittingLoginForm(
"subtst_notifications_2pw_0un.html",
async function(fieldValues) {
is(fieldValues.username, "null", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-change");
ok(notif, "got notification popup");
await cleanupDoorhanger(notif);
}
);
await testSubmittingLoginForm("subtst_notifications_2pw_0un.html", function(
fieldValues
) {
is(fieldValues.username, "null", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = getCaptureDoorhanger("password-change");
ok(notif, "got notification popup");
notif.remove();
});
let logins = Services.logins.getAllLogins();
is(logins.length, 1, "Should only have 1 login");
@ -687,16 +683,15 @@ add_task(async function test_change2pw0unExistingDifferentP() {
Services.logins.addLogin(login2B);
await testSubmittingLoginForm(
"subtst_notifications_2pw_0un.html",
async function(fieldValues) {
is(fieldValues.username, "null", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-change");
ok(notif, "got notification popup");
await cleanupDoorhanger(notif);
}
);
await testSubmittingLoginForm("subtst_notifications_2pw_0un.html", function(
fieldValues
) {
is(fieldValues.username, "null", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = getCaptureDoorhanger("password-change");
ok(notif, "got notification popup");
notif.remove();
});
let logins = Services.logins.getAllLogins();
is(logins.length, 1, "Should only have 1 login");
@ -746,7 +741,7 @@ add_task(async function test_changeUPLoginOnPUpdateForm() {
async function(fieldValues) {
is(fieldValues.username, "null", "Checking submitted username");
is(fieldValues.password, "pass2", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-change");
let notif = getCaptureDoorhanger("password-change");
ok(notif, "got notification popup");
await checkDoorhangerUsernamePassword("notifyu1", "pass2");
@ -781,7 +776,7 @@ add_task(async function test_recipeCaptureFields_NewLogin() {
async function(fieldValues) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
// Sanity check, no logins should exist yet.
@ -837,7 +832,7 @@ add_task(async function test_noShowPasswordOnDismissal() {
fieldValues
) {
info("Opening popup");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
let { panel } = PopupNotifications;
info("Hiding popup.");
@ -858,7 +853,6 @@ add_task(async function test_noShowPasswordOnDismissal() {
true,
"Check that the Show Password field is Hidden"
);
await cleanupDoorhanger(notif);
});
});
@ -869,7 +863,7 @@ add_task(async function test_showPasswordOn1stOpenOfDismissedByDefault() {
fieldValues
) {
info("Opening popup");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
let { panel } = PopupNotifications;
info("Hiding popup.");
@ -890,7 +884,6 @@ add_task(async function test_showPasswordOn1stOpenOfDismissedByDefault() {
true,
"Check that the Show Password field is Hidden"
);
await cleanupDoorhanger(notif);
});
});

View File

@ -71,7 +71,7 @@ add_task(async function test_httpsUpgradeCaptureFields_changePW() {
async function(fieldValues) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "pass2", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-change");
let notif = getCaptureDoorhanger("password-change");
ok(notif, "checking for a change popup");
await checkDoorhangerUsernamePassword("notifyu1", "pass2");
@ -115,7 +115,7 @@ add_task(
async function(fieldValues) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "pass2", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-change");
let notif = getCaptureDoorhanger("password-change");
ok(notif, "checking for a change popup");
await checkDoorhangerUsernamePassword("notifyu1", "pass2");
@ -178,7 +178,7 @@ add_task(async function test_httpsUpgradeCaptureFields_captureMatchingHTTP() {
) {
is(fieldValues.username, "notifyu1", "Checking submitted username");
is(fieldValues.password, "notifyp1", "Checking submitted password");
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
is(

View File

@ -71,7 +71,7 @@ add_task(async function test_saveChromeHiddenAutoClose() {
info("waiting for popupshown");
await notifShownPromise;
// the popup closes and the doorhanger should appear in the opener
let popup = await getCaptureDoorhangerThatMayOpen("password-save");
let popup = getCaptureDoorhanger("password-save");
ok(popup, "got notification popup");
await checkDoorhangerUsernamePassword("notifyu1", "notifyp1");
// Sanity check, no logins should exist yet.
@ -99,7 +99,7 @@ add_task(async function test_changeChromeHiddenAutoClose() {
await withTestTabUntilStorageChange(url, async function() {
info("waiting for popupshown");
await notifShownPromise;
let popup = await getCaptureDoorhangerThatMayOpen("password-change");
let popup = getCaptureDoorhanger("password-change");
ok(popup, "got notification popup");
await checkDoorhangerUsernamePassword("notifyu1", "pass2");
clickDoorhangerButton(popup, CHANGE_BUTTON);
@ -133,7 +133,7 @@ add_task(async function test_saveChromeVisibleSameWindow() {
);
await withTestTabUntilStorageChange(url, async function() {
await notifShownPromise;
let popup = await getCaptureDoorhangerThatMayOpen("password-save");
let popup = getCaptureDoorhanger("password-save");
ok(popup, "got notification popup");
await checkDoorhangerUsernamePassword("notifyu2", "notifyp2");
clickDoorhangerButton(popup, REMEMBER_BUTTON);
@ -157,7 +157,7 @@ add_task(async function test_changeChromeVisibleSameWindow() {
);
await withTestTabUntilStorageChange(url, async function() {
await notifShownPromise;
let popup = await getCaptureDoorhangerThatMayOpen("password-change");
let popup = getCaptureDoorhanger("password-change");
ok(popup, "got notification popup");
await checkDoorhangerUsernamePassword("notifyu2", "pass2");
clickDoorhangerButton(popup, CHANGE_BUTTON);

View File

@ -344,7 +344,6 @@ add_task(async function fill_generated_password_with_matching_logins() {
);
Services.logins.removeAllLogins();
LoginTestUtils.resetGeneratedPasswordsCache();
});
add_task(async function test_edited_generated_password_in_new_tab() {
@ -449,6 +448,5 @@ add_task(async function test_edited_generated_password_in_new_tab() {
);
Services.logins.removeAllLogins();
LoginTestUtils.resetGeneratedPasswordsCache();
await SpecialPowers.popPrefEnv();
});

View File

@ -47,7 +47,6 @@ add_task(async function test_doorhanger_dismissal_un() {
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
ok(notif.dismissed, "notification popup was automatically dismissed");
await cleanupDoorhanger(notif);
}
);
});
@ -83,7 +82,6 @@ add_task(async function test_doorhanger_dismissal_pw() {
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
ok(notif.dismissed, "notification popup was automatically dismissed");
await cleanupDoorhanger(notif);
}
);
});
@ -109,13 +107,12 @@ add_task(async function test_doorhanger_shown_on_un_with_invalid_ccnumber() {
});
await processedPromise;
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
ok(
!notif.dismissed,
"notification popup was not automatically dismissed"
);
await cleanupDoorhanger(notif);
}
);
});
@ -156,7 +153,6 @@ add_task(async function test_doorhanger_dismissal_on_change() {
let notif = getCaptureDoorhanger("password-save");
ok(notif, "got notification popup");
ok(notif.dismissed, "notification popup was automatically dismissed");
await cleanupDoorhanger(notif);
}
);
});

View File

@ -38,9 +38,6 @@ add_task(async function test_disable() {
let promiseChanged = promiseStorageChanged("hostSavingDisabled");
await BrowserTestUtils.waitForEvent(dialog, "load");
await new Promise(resolve => {
waitForFocus(resolve, dialog);
});
Services.logins.setLoginSavingEnabled(LOGIN_HOST, false);
await promiseChanged;
is(countDisabledHosts(dialog), 1, "Verify disabled host added");
@ -52,9 +49,6 @@ add_task(async function test_enable() {
let promiseChanged = promiseStorageChanged("hostSavingEnabled");
await BrowserTestUtils.waitForEvent(dialog, "load");
await new Promise(resolve => {
waitForFocus(resolve, dialog);
});
Services.logins.setLoginSavingEnabled(LOGIN_HOST, true);
await promiseChanged;
is(countDisabledHosts(dialog), 0, "Verify disabled host removed");

View File

@ -13,12 +13,11 @@ const FORM_PAGE_PATH =
const passwordInputSelector = "#form-basic-password";
const usernameInputSelector = "#form-basic-username";
let login1;
async function setup_withOneLogin(username = "username", password = "pass1") {
// Reset to a single, known login
Services.logins.removeAllLogins();
LoginTestUtils.resetGeneratedPasswordsCache();
let login = await LoginTestUtils.addLogin({ username, password });
return login;
login1 = await LoginTestUtils.addLogin({ username, password });
}
async function setup_withNoLogins() {
@ -29,7 +28,6 @@ async function setup_withNoLogins() {
0,
"0 logins at the start of the test"
);
LoginTestUtils.resetGeneratedPasswordsCache();
}
async function fillGeneratedPasswordFromACPopup(
@ -218,17 +216,17 @@ async function openAndVerifyDoorhanger(browser, type, expected) {
expected.anchorExtraAttr,
"Check icon extraAttr attribute"
);
let { panel } = PopupNotifications;
// if the doorhanged is dimissed, we will open it to check panel contents
if (panel.state !== "open") {
let promiseShown = BrowserTestUtils.waitForEvent(panel, "popupshown");
if (panel.state !== "showing") {
// synthesize click on anchor as this also blurs the form field triggering
// a change event
EventUtils.synthesizeMouseAtCenter(notif.anchorElement, {});
}
if (!PopupNotifications.isPanelOpen) {
let promiseShown = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popupshown"
);
await SimpleTest.promiseFocus(browser);
info("Clicking on anchor to show popup.");
notif.anchorElement.click();
await promiseShown;
}
// if the doorhanged is dimissed, we will open it to check panel contents
let { passwordValue, usernameValue } = await checkPromptContents(
notif.anchorElement,
browser,
@ -247,7 +245,7 @@ async function openAndVerifyDoorhanger(browser, type, expected) {
return notif;
}
async function hideDoorhangerPopup() {
async function hideDoorhangerPopup(browser) {
info("hideDoorhangerPopup");
if (!PopupNotifications.isPanelOpen) {
return;
@ -275,6 +273,33 @@ async function submitForm(browser) {
});
}
function verifyLogins(expectedValues) {
let allLogins = Services.logins.getAllLogins();
is(allLogins.length, expectedValues.count, "Check saved logins count");
for (let i = 0; i < expectedValues.loginProperties.length; i++) {
let expected = expectedValues[i];
if (expected) {
let login = allLogins[i];
if (expected.hasOwnProperty("timesUsed")) {
is(login.timesUsed, expected.timesUsed, "Check timesUsed");
}
if (expected.hasOwnProperty("passwordLength")) {
is(
login.password.length,
expected.passwordLength,
"Check passwordLength"
);
}
if (expected.hasOwnProperty("username")) {
is(login.username, expected.username, "Check username");
}
if (expected.hasOwnProperty("usedSince")) {
ok(login.timeLastUsed > expected.usedSince, "Check timeLastUsed");
}
}
}
}
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({
set: [
@ -328,20 +353,13 @@ add_task(async function autocomplete_generated_password_auto_saved() {
usernameValue: "",
passwordLength: LoginTestUtils.generation.LENGTH,
});
let promiseHidden = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popuphidden"
);
clickDoorhangerButton(notif, DONT_CHANGE_BUTTON);
await promiseHidden;
await clickDoorhangerButton(notif, DONT_CHANGE_BUTTON);
// confirm the extraAttr attribute is removed after opening & dismissing the doorhanger
ok(
!notif.anchorElement.hasAttribute("extraAttr"),
"Check if the extraAttr attribute was removed"
);
await cleanupDoorhanger(notif);
notif.remove();
storageChangedPromise = TestUtils.topicObserved(
"passwordmgr-storage-changed",
@ -351,12 +369,16 @@ add_task(async function autocomplete_generated_password_auto_saved() {
info("waiting for submitForm");
await submitForm(browser);
await storageChangedPromise;
verifyLogins([
{
timesUsed: autoSavedLogin.timesUsed + 1,
username: "",
},
]);
verifyLogins({
count: 1,
loginProperties: [
{
timesUsed: autoSavedLogin.timesUsed + 1,
username: "",
},
],
});
await hideDoorhangerPopup(browser); // make sure the popup is closed for next test
}
);
});
@ -390,7 +412,7 @@ add_task(async function autocomplete_generated_password_saved_empty_username() {
usernameValue: "",
passwordLength: LoginTestUtils.generation.LENGTH,
});
await hideDoorhangerPopup();
await hideDoorhangerPopup(browser);
info("Waiting to verifyGeneratedPasswordWasFilled");
await verifyGeneratedPasswordWasFilled(browser, passwordInputSelector);
@ -403,22 +425,20 @@ add_task(async function autocomplete_generated_password_saved_empty_username() {
passwordLength: LoginTestUtils.generation.LENGTH,
});
let promiseHidden = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popuphidden"
);
clickDoorhangerButton(notif, CHANGE_BUTTON);
await promiseHidden;
await clickDoorhangerButton(notif, CHANGE_BUTTON);
info("Waiting for modifyLogin");
await storageChangedPromise;
verifyLogins([
{
timesUsed: savedLogin.timesUsed + 1,
username: "",
},
]);
await cleanupDoorhanger(notif); // cleanup the doorhanger for next test
verifyLogins({
count: 1,
loginProperties: [
{
timesUsed: savedLogin.timesUsed + 1,
username: "",
},
],
});
await hideDoorhangerPopup(browser); // make sure the popup is closed for next test
notif && notif.remove();
}
);
});
@ -456,7 +476,7 @@ add_task(async function ac_gen_pw_saved_empty_un_stored_non_empty_un_in_form() {
usernameValue: "myusername",
passwordLength: LoginTestUtils.generation.LENGTH,
});
await hideDoorhangerPopup();
await hideDoorhangerPopup(browser);
info("Waiting to verifyGeneratedPasswordWasFilled");
await verifyGeneratedPasswordWasFilled(browser, passwordInputSelector);
@ -469,27 +489,25 @@ add_task(async function ac_gen_pw_saved_empty_un_stored_non_empty_un_in_form() {
passwordLength: LoginTestUtils.generation.LENGTH,
});
let promiseHidden = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popuphidden"
);
clickDoorhangerButton(notif, REMEMBER_BUTTON);
await promiseHidden;
await clickDoorhangerButton(notif, REMEMBER_BUTTON);
info("Waiting for addLogin");
await storageChangedPromise;
verifyLogins([
{
timesUsed: savedLogin.timesUsed,
username: "",
password: "xyzpassword",
},
{
timesUsed: 1,
username: "myusername",
},
]);
await cleanupDoorhanger(notif); // cleanup the doorhanger for next test
verifyLogins({
count: 2,
loginProperties: [
{
timesUsed: savedLogin.timesUsed,
username: "",
password: "xyzpassword",
},
{
timesUsed: 1,
username: "myusername",
},
],
});
await hideDoorhangerPopup(browser); // make sure the popup is closed for next test
notif && notif.remove();
}
);
});
@ -526,7 +544,7 @@ add_task(async function contextfill_generated_password_saved_empty_username() {
usernameValue: "",
passwordLength: LoginTestUtils.generation.LENGTH,
});
await hideDoorhangerPopup();
await hideDoorhangerPopup(browser);
info("Waiting to verifyGeneratedPasswordWasFilled");
await verifyGeneratedPasswordWasFilled(browser, passwordInputSelector);
@ -539,22 +557,20 @@ add_task(async function contextfill_generated_password_saved_empty_username() {
passwordLength: LoginTestUtils.generation.LENGTH,
});
let promiseHidden = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popuphidden"
);
clickDoorhangerButton(notif, CHANGE_BUTTON);
await promiseHidden;
await clickDoorhangerButton(notif, CHANGE_BUTTON);
info("Waiting for modifyLogin");
await storageChangedPromise;
verifyLogins([
{
timesUsed: savedLogin.timesUsed + 1,
username: "",
},
]);
await cleanupDoorhanger(notif); // cleanup the doorhanger for next test
verifyLogins({
count: 1,
loginProperties: [
{
timesUsed: savedLogin.timesUsed + 1,
username: "",
},
],
});
await hideDoorhangerPopup(browser); // make sure the popup is closed for next test
notif && notif.remove();
}
);
});
@ -589,14 +605,7 @@ add_task(async function autocomplete_generated_password_edited_no_auto_save() {
usernameValue: "",
passwordLength: LoginTestUtils.generation.LENGTH,
});
let promiseHidden = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popuphidden"
);
clickDoorhangerButton(notif, DONT_CHANGE_BUTTON);
await promiseHidden;
await clickDoorhangerButton(notif, DONT_CHANGE_BUTTON);
info("Waiting to verifyGeneratedPasswordWasFilled");
await verifyGeneratedPasswordWasFilled(browser, passwordInputSelector);
@ -612,21 +621,18 @@ add_task(async function autocomplete_generated_password_edited_no_auto_save() {
usernameValue: "",
passwordLength: LoginTestUtils.generation.LENGTH + 2,
});
await clickDoorhangerButton(notif, DONT_CHANGE_BUTTON);
promiseHidden = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popuphidden"
);
clickDoorhangerButton(notif, DONT_CHANGE_BUTTON);
await promiseHidden;
verifyLogins([
{
timesUsed: savedLogin.timesUsed,
username: "",
password: "xyzpassword",
},
]);
verifyLogins({
count: 1,
loginProperties: [
{
timesUsed: savedLogin.timesUsed,
username: "",
password: "xyzpassword",
},
],
});
info("waiting for submitForm");
await submitForm(browser);
@ -637,22 +643,20 @@ add_task(async function autocomplete_generated_password_edited_no_auto_save() {
passwordLength: LoginTestUtils.generation.LENGTH + 2,
});
promiseHidden = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popuphidden"
);
clickDoorhangerButton(notif, CHANGE_BUTTON);
await promiseHidden;
await clickDoorhangerButton(notif, CHANGE_BUTTON);
info("Waiting for modifyLogin");
await storageChangedPromise;
verifyLogins([
{
timesUsed: savedLogin.timesUsed + 1,
username: "",
},
]);
await cleanupDoorhanger(notif); // cleanup the doorhanger for next test
verifyLogins({
count: 1,
loginProperties: [
{
timesUsed: savedLogin.timesUsed + 1,
username: "",
},
],
});
await hideDoorhangerPopup(browser); // make sure the popup is closed for next test
notif && notif.remove();
}
);
@ -705,7 +709,7 @@ add_task(async function contextmenu_fill_generated_password_and_set_username() {
browser,
passwordInputSelector
);
info("waiting for dismissed password-change notification");
info("waiting for password-change doorhanger");
await waitForDoorhanger(browser, "password-change");
// Make sure confirmation hint was shown
await hintPromiseShown;
@ -713,16 +717,18 @@ add_task(async function contextmenu_fill_generated_password_and_set_username() {
info("waiting for addLogin");
await storageChangedPromise;
// Check properties of the newly auto-saved login
verifyLogins([
null, // ignore the first one
{
timesUsed: 1,
username: "",
passwordLength: LoginTestUtils.generation.LENGTH,
},
]);
verifyLogins({
count: 2,
loginProperties: [
null, // ignore the first one
{
timesUsed: 1,
username: "",
passwordLength: LoginTestUtils.generation.LENGTH,
},
],
});
info("Waiting to openAndVerifyDoorhanger");
await openAndVerifyDoorhanger(browser, "password-change", {
@ -731,7 +737,7 @@ add_task(async function contextmenu_fill_generated_password_and_set_username() {
usernameValue: "differentuser",
passwordLength: LoginTestUtils.generation.LENGTH,
});
await hideDoorhangerPopup();
await hideDoorhangerPopup(browser);
info("Waiting to verifyGeneratedPasswordWasFilled");
await verifyGeneratedPasswordWasFilled(browser, passwordInputSelector);
@ -748,25 +754,22 @@ add_task(async function contextmenu_fill_generated_password_and_set_username() {
"passwordmgr-storage-changed",
(_, data) => data == "modifyLogin"
);
let promiseHidden = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popuphidden"
);
clickDoorhangerButton(notif, CHANGE_BUTTON);
await promiseHidden;
await clickDoorhangerButton(notif, CHANGE_BUTTON);
info("Waiting for modifyLogin");
await storageChangedPromise;
verifyLogins([
null,
{
username: "differentuser",
passwordLength: LoginTestUtils.generation.LENGTH,
timesUsed: 2,
},
]);
await cleanupDoorhanger(notif); // cleanup the doorhanger for next test
verifyLogins({
count: 2,
loginProperties: [
null,
{
username: "differentuser",
passwordLength: LoginTestUtils.generation.LENGTH,
timesUsed: 1,
},
],
});
await hideDoorhangerPopup(browser); // make sure the popup is closed for next test
notif && notif.remove();
}
);
});
@ -806,7 +809,7 @@ add_task(async function contextmenu_password_change_form_without_username() {
passwordInputSelector
);
info("waiting for dismissed password-change notification");
info("waiting for password-change doorhanger");
await waitForDoorhanger(browser, "password-change");
// Make sure confirmation hint was shown
await hintPromiseShown;
@ -815,15 +818,18 @@ add_task(async function contextmenu_password_change_form_without_username() {
info("waiting for addLogin");
await storageChangedPromise;
// Check properties of the newly auto-saved login
verifyLogins([
null, // ignore the first one
null, // ignore the 2nd one
{
timesUsed: 1,
username: "",
passwordLength: LoginTestUtils.generation.LENGTH,
},
]);
verifyLogins({
count: 3,
loginProperties: [
null, // ignore the first one
null, // ignore the 2nd one
{
timesUsed: 1,
username: "",
passwordLength: LoginTestUtils.generation.LENGTH,
},
],
});
info("Waiting to openAndVerifyDoorhanger");
let notif = await openAndVerifyDoorhanger(browser, "password-change", {
@ -832,8 +838,9 @@ add_task(async function contextmenu_password_change_form_without_username() {
usernameValue: "",
passwordLength: LoginTestUtils.generation.LENGTH,
});
await hideDoorhangerPopup(browser);
// remove notification so we can unambiguously check no new notification gets created later
await cleanupDoorhanger(notif);
notif && notif.remove();
info("Waiting to verifyGeneratedPasswordWasFilled");
await verifyGeneratedPasswordWasFilled(browser, passwordInputSelector);
@ -849,209 +856,20 @@ add_task(async function contextmenu_password_change_form_without_username() {
info("Waiting for modifyLogin");
await storageChangedPromise;
verifyLogins([
null, // ignore the first one
null, // ignore the 2nd one
{
timesUsed: 2,
usedSince: timeLastUsed,
},
]);
verifyLogins({
count: 3,
loginProperties: [
null, // ignore the first one
null, // ignore the 2nd one
{
timesUsed: 2,
usedSince: timeLastUsed,
},
],
});
// Check no new doorhanger was shown
notif = getCaptureDoorhanger("password-change");
ok(!notif, "No new doorhanger should be shown");
await cleanupDoorhanger(); // cleanup for next test
}
);
});
add_task(async function autosaved_login_updated_to_existing_login() {
// test when filling with a generated password and editing the username in the
// doorhanger to match an existing login:
// * the matching login should be updated
// * the auto-saved login should be deleted
// * the metadata for the matching login should be updated
// * the by-origin cache for the password should point at the updated login
await setup_withOneLogin("user1", "xyzpassword");
await LoginTestUtils.addLogin({ username: "user2", password: "abcpassword" });
await openFormInNewTab(
TEST_ORIGIN + FORM_PAGE_PATH,
{
password: {
selector: passwordInputSelector,
expectedValue: "",
},
username: {
selector: usernameInputSelector,
expectedValue: "",
},
},
async function taskFn(browser) {
await SimpleTest.promiseFocus(browser.ownerGlobal);
let storageChangedPromise = TestUtils.topicObserved(
"passwordmgr-storage-changed",
(_, data) => data == "addLogin"
);
let confirmationHint = document.getElementById("confirmation-hint");
let hintPromiseShown = BrowserTestUtils.waitForEvent(
confirmationHint,
"popupshown"
);
info("waiting to fill generated password using context menu");
await doFillGeneratedPasswordContextMenuItem(
browser,
passwordInputSelector
);
info("waiting for dismissed password-change notification");
await waitForDoorhanger(browser, "password-change");
// Make sure confirmation hint was shown
await hintPromiseShown;
await verifyConfirmationHint(confirmationHint);
info("waiting for addLogin");
await storageChangedPromise;
info("addLogin promise resolved");
// Check properties of the newly auto-saved login
let [user1LoginSnapshot, unused, autoSavedLogin] = verifyLogins([
null, // ignore the first one
null, // ignore the 2nd one
{
timesUsed: 1,
username: "",
passwordLength: LoginTestUtils.generation.LENGTH,
},
]);
info("user1LoginSnapshot, guid: " + user1LoginSnapshot.guid);
info("unused, guid: " + unused.guid);
info("autoSavedLogin, guid: " + autoSavedLogin.guid);
info("verifyLogins ok");
let passwordCacheEntry = LoginManagerParent._generatedPasswordsByPrincipalOrigin.get(
"https://example.com"
);
ok(
passwordCacheEntry,
"Got the cached generated password entry for https://example.com"
);
is(
passwordCacheEntry.value,
autoSavedLogin.password,
"Cached password matches the auto-saved login password"
);
is(
passwordCacheEntry.storageGUID,
autoSavedLogin.guid,
"Cached password guid matches the auto-saved login guid"
);
let messagePromise = new Promise(resolve => {
const eventName = "PasswordManager:onGeneratedPasswordFilledOrEdited";
browser.messageManager.addMessageListener(
eventName,
function mgsHandler(msg) {
if (msg.target != browser) {
return;
}
browser.messageManager.removeMessageListener(eventName, mgsHandler);
info("Got onGeneratedPasswordFilledOrEdited, resolving");
// allow LMP to handle the message, then resolve
SimpleTest.executeSoon(resolve);
}
);
});
info("Waiting to openAndVerifyDoorhanger");
// also moves focus, producing another onGeneratedPasswordFilledOrEdited message from content
let notif = await openAndVerifyDoorhanger(browser, "password-change", {
dismissed: true,
anchorExtraAttr: "attention",
usernameValue: "",
password: autoSavedLogin.password,
});
ok(notif, "Got password-change notification");
// content sends a 2nd message when we blur the password field,
// wait for that before interacting with doorhanger
info("waiting for messagePromise");
await messagePromise;
info("Calling updateDoorhangerInputValues");
await updateDoorhangerInputValues({
username: "user1",
});
info("doorhanger inputs updated");
let loginModifiedPromise = TestUtils.topicObserved(
"passwordmgr-storage-changed",
(_, data) => {
if (data == "modifyLogin") {
info("passwordmgr-storage-changed, action: " + data);
info("subject: " + JSON.stringify(_));
return true;
}
return false;
}
);
let loginRemovedPromise = TestUtils.topicObserved(
"passwordmgr-storage-changed",
(_, data) => {
if (data == "removeLogin") {
info("passwordmgr-storage-changed, action: " + data);
info("subject: " + JSON.stringify(_));
return true;
}
return false;
}
);
let promiseHidden = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popuphidden"
);
info("clicking change button");
clickDoorhangerButton(notif, CHANGE_BUTTON);
await promiseHidden;
info("Waiting for modifyLogin promise");
await loginModifiedPromise;
info("Waiting for removeLogin promise");
await loginRemovedPromise;
info("storage-change promises resolved");
// Check the auto-saved login was removed and the original login updated
let savedLogins = verifyLogins([
{
username: "user1",
password: autoSavedLogin.password,
timeCreated: user1LoginSnapshot.timeCreated,
timeLastUsed: user1LoginSnapshot.timeLastUsed,
passwordChangedSince: autoSavedLogin.timePasswordChanged,
},
null, // ignore user2
]);
// Check we have no notifications at this point
ok(!PopupNotifications.isPanelOpen, "No doorhanger is open");
ok(
!PopupNotifications.getNotification("password", browser),
"No notifications"
);
// make sure the cache entry is up to date:
let updatedLogin = savedLogins[0];
passwordCacheEntry = LoginManagerParent._generatedPasswordsByPrincipalOrigin.get(
"https://example.com"
);
todo_is(
passwordCacheEntry.storageGUID,
updatedLogin.guid,
"Generated password cache entry points at the correct login"
);
}
);
});

View File

@ -7,77 +7,31 @@ add_task(async function test_save_change() {
{
username: "username",
password: "password",
expectOutcome: [
{
username: "username",
password: "password",
},
],
},
{
username: "",
password: "password",
expectOutcome: [
{
username: "",
password: "password",
},
],
},
{
username: "username",
oldPassword: "password",
password: "newPassword",
expectOutcome: [
{
username: "username",
password: "newPassword",
},
],
},
{
username: "",
oldPassword: "password",
password: "newPassword",
expectOutcome: [
{
username: "",
password: "newPassword",
},
],
},
{
oldUsername: "",
username: "username",
oldPassword: "password",
password: "newPassword",
expectOutcome: [
{
username: "",
password: "password",
},
{
username: "username",
password: "newPassword",
},
],
},
];
for (let {
oldUsername,
username,
oldPassword,
password,
expectOutcome,
} of testCases) {
for (let { username, oldPassword, password } of testCases) {
// Add a login for the origin of the form if testing a change notification.
if (oldPassword) {
Services.logins.addLogin(
LoginTestUtils.testData.formLogin({
origin: "https://example.com",
formActionOrigin: "https://example.com",
username: typeof oldUsername !== "undefined" ? oldUsername : username,
username,
password: oldPassword,
})
);
@ -108,7 +62,6 @@ add_task(async function test_save_change() {
doc.getElementById("form-basic").submit();
});
await promiseShown;
let notif = PopupNotifications.getNotification("password", browser);
let notificationElement = PopupNotifications.panel.childNodes[0];
// Style flush to make sure binding is attached
notificationElement.querySelector("#password-notification-password")
@ -129,24 +82,22 @@ add_task(async function test_save_change() {
// Simulate the action on the notification to request the login to be
// saved, and wait for the data to be updated or saved based on the type
// of operation we expect.
let expectedNotification;
if (oldPassword !== undefined && oldUsername !== undefined) {
expectedNotification = "addLogin";
} else if (oldPassword !== undefined) {
expectedNotification = "modifyLogin";
} else {
expectedNotification = "addLogin";
}
let expectedNotification = oldPassword ? "modifyLogin" : "addLogin";
let promiseLogin = TestUtils.topicObserved(
"passwordmgr-storage-changed",
(_, data) => data == expectedNotification
);
notificationElement.button.doCommand();
await promiseLogin;
await cleanupDoorhanger(notif); // clean slate for the next test
let [result] = await promiseLogin;
// Check that the values in the database match the expected values.
verifyLogins(expectOutcome);
let login = oldPassword
? result
.QueryInterface(Ci.nsIArray)
.queryElementAt(1, Ci.nsILoginInfo)
: result.QueryInterface(Ci.nsILoginInfo);
Assert.equal(login.username, username);
Assert.equal(login.password, password);
}
);

View File

@ -188,7 +188,7 @@ add_task(async function test_normal_popup_notification_1() {
() => !notif.dismissed,
"notification should not be dismissed"
);
await cleanupDoorhanger(notif);
notif.remove();
}
}
);
@ -259,7 +259,7 @@ add_task(async function test_private_popup_notification_2() {
ok(toggleCheckbox.hidden, "Toggle should be hidden upon 2nd opening");
await cleanupDoorhanger(notif);
notif.remove();
}
}
);
@ -307,7 +307,7 @@ add_task(async function test_private_popup_notification_no_capture_pref_2b() {
ok(!notif, "Expected no notification popup");
if (notif) {
await cleanupDoorhanger(notif);
notif.remove();
}
}
);
@ -349,7 +349,7 @@ add_task(async function test_normal_popup_notification_3() {
);
ok(!notif, "got no notification popup");
if (notif) {
await cleanupDoorhanger(notif);
notif.remove();
}
}
);
@ -400,7 +400,7 @@ add_task(async function test_private_popup_notification_3b() {
);
ok(!notif, "got no notification popup");
if (notif) {
await cleanupDoorhanger(notif);
notif.remove();
}
}
);
@ -453,7 +453,7 @@ add_task(async function test_normal_new_password_4() {
() => !notif.dismissed,
"notification should not be dismissed"
);
await cleanupDoorhanger(notif);
notif.remove();
}
}
);
@ -515,7 +515,7 @@ add_task(async function test_private_new_password_5() {
() => !notif.dismissed,
"notification should not be dismissed"
);
await cleanupDoorhanger(notif);
notif.remove();
}
}
);
@ -563,7 +563,7 @@ add_task(async function test_normal_with_login_6() {
() => !notif.dismissed,
"notification should not be dismissed"
);
await cleanupDoorhanger(notif);
notif.remove();
}
Services.logins.removeLogin(login);
}
@ -729,7 +729,7 @@ add_task(async function test_normal_http_basic_auth() {
() => !notif.dismissed,
"notification should not be dismissed"
);
await cleanupDoorhanger(notif);
notif.remove();
}
}
);
@ -774,7 +774,7 @@ add_task(async function test_private_http_basic_auth() {
() => notif.dismissed,
"notification should be dismissed"
);
await cleanupDoorhanger(notif);
notif.remove();
}
}
);
@ -820,7 +820,7 @@ add_task(async function test_private_http_basic_auth_no_capture_pref() {
ok(!notif, "got no notification popup");
if (notif) {
await cleanupDoorhanger(notif);
notif.remove();
}
}
);

View File

@ -1,606 +0,0 @@
/**
* Test result of different input to the promptToChangePassword doorhanger
*/
"use strict";
// The origin for the test URIs.
const TEST_ORIGIN = "https://example.com";
const passwordInputSelector = "#form-basic-password";
const usernameInputSelector = "#form-basic-username";
const availLoginsByValue = new Map();
let savedLoginsByName;
const finalLoginsByGuid = new Map();
let finalLogins;
const availLogins = {
emptyXYZ: LoginTestUtils.testData.formLogin({
username: "",
password: "xyz",
}),
bobXYZ: LoginTestUtils.testData.formLogin({
username: "bob",
password: "xyz",
}),
bobABC: LoginTestUtils.testData.formLogin({
username: "bob",
password: "abc",
}),
};
availLoginsByValue.set(availLogins.emptyXYZ, "emptyXYZ");
availLoginsByValue.set(availLogins.bobXYZ, "bobXYZ");
availLoginsByValue.set(availLogins.bobABC, "bobABC");
async function showChangePasswordDoorhanger(
browser,
oldLogin,
formLogin,
{ notificationType = "password-change", autoSavedLoginGuid = "" } = {}
) {
let prompter = LoginManagerParent._getPrompter(browser, null);
ok(!PopupNotifications.isPanelOpen, "Check the doorhanger isnt already open");
let promiseShown = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popupshown"
);
prompter.promptToChangePassword(
oldLogin,
formLogin,
false, // dimissed prompt
false, // notifySaved
autoSavedLoginGuid
);
await promiseShown;
let notif = getCaptureDoorhanger(notificationType);
ok(notif, `${notificationType} notification exists`);
let { panel } = PopupNotifications;
let notificationElement = panel.childNodes[0];
await BrowserTestUtils.waitForCondition(() => {
return (
notificationElement.querySelector("#password-notification-password")
.value == formLogin.password &&
notificationElement.querySelector("#password-notification-username")
.value == formLogin.username
);
}, "Wait for the notification panel to be populated");
return notif;
}
async function setupLogins(...logins) {
Services.logins.removeAllLogins();
let savedLogins = {};
let timesCreated = new Set();
for (let login of logins) {
let loginName = availLoginsByValue.get(login);
let savedLogin = await LoginTestUtils.addLogin(login);
// we rely on sorting by timeCreated so ensure none are identical
ok(
!timesCreated.has(savedLogin.timeCreated),
"Each login has a different timeCreated"
);
timesCreated.add(savedLogin.timeCreated);
savedLogins[loginName || savedLogin.guid] = savedLogin.clone();
}
return savedLogins;
}
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({
set: [["signon.autofillForms", false]],
});
ok(!PopupNotifications.isPanelOpen, "No notifications panel open");
});
async function promptToChangePasswordTest(testData) {
info("Starting: " + testData.name);
let browser = gBrowser.selectedBrowser;
savedLoginsByName = await setupLogins(...testData.initialSavedLogins);
await SimpleTest.promiseFocus();
info("got focus");
let oldLogin = savedLoginsByName[testData.promptArgs.oldLogin];
let changeLogin = LoginTestUtils.testData.formLogin(
testData.promptArgs.changeLogin
);
let options;
if (testData.autoSavedLoginName) {
options = {
autoSavedLoginGuid: savedLoginsByName[testData.autoSavedLoginName].guid,
};
}
info(
"Waiting for showChangePasswordDoorhanger, username: " +
changeLogin.username
);
let notif = await showChangePasswordDoorhanger(
browser,
oldLogin,
changeLogin,
options
);
await updateDoorhangerInputValues(testData.promptTextboxValues);
let mainActionButton = getDoorhangerButton(notif, CHANGE_BUTTON);
is(
mainActionButton.label,
testData.expectedButtonLabel,
"Check button label"
);
let { panel } = PopupNotifications;
let promiseHidden = BrowserTestUtils.waitForEvent(panel, "popuphidden");
let storagePromise;
if (testData.expectedStorageChange) {
storagePromise = TestUtils.topicObserved("passwordmgr-storage-changed");
}
info("Clicking mainActionButton");
mainActionButton.doCommand();
info("Waiting for promiseHidden");
await promiseHidden;
info("Waiting for storagePromise");
await storagePromise;
// ensure the notification was removed to keep clean state for next run
await cleanupDoorhanger(notif);
info(testData.resultDescription);
finalLoginsByGuid.clear();
finalLogins = Services.logins.getAllLogins();
finalLogins.sort((a, b) => a.timeCreated > b.timeCreated);
for (let l of finalLogins) {
info(`saved login: ${l.guid}: ${l.username}/${l.password}`);
finalLoginsByGuid.set(l.guid, l);
}
info("verifyLogins next");
verifyLogins(testData.expectedResultLogins);
if (testData.resultCheck) {
testData.resultCheck();
}
}
let tests = [
{
name: "Add username to sole login",
initialSavedLogins: [availLogins.emptyXYZ],
promptArgs: {
oldLogin: "emptyXYZ",
changeLogin: {
username: "zaphod",
password: "xyz",
},
},
promptTextboxValues: {},
expectedButtonLabel: "Update",
resultDescription: "The existing login just gets a new password",
expectedStorageChange: true,
expectedResultLogins: [
{
username: "zaphod",
password: "xyz",
},
],
resultCheck() {
is(finalLogins[0].guid, savedLoginsByName.emptyXYZ.guid, "Check guid");
},
},
{
name: "Change password of the sole login",
initialSavedLogins: [availLogins.bobXYZ],
promptArgs: {
oldLogin: "bobXYZ",
changeLogin: {
username: "bob",
password: "&*$",
},
},
promptTextboxValues: {},
expectedButtonLabel: "Update",
resultDescription: "The existing login just gets a new password",
expectedStorageChange: true,
expectedResultLogins: [
{
username: "bob",
password: "&*$",
},
],
resultCheck() {
is(finalLogins[0].guid, savedLoginsByName.bobXYZ.guid, "Check guid");
},
},
{
name: "Change password of the sole empty-username login",
initialSavedLogins: [availLogins.emptyXYZ],
promptArgs: {
oldLogin: "emptyXYZ",
changeLogin: {
username: "",
password: "&*$",
},
},
promptTextboxValues: {},
expectedButtonLabel: "Update",
resultDescription: "The existing login just gets a new password",
expectedStorageChange: true,
expectedResultLogins: [
{
username: "",
password: "&*$",
},
],
resultCheck() {
is(finalLogins[0].guid, savedLoginsByName.emptyXYZ.guid, "Check guid");
},
},
{
name: "Add different username to empty-usernamed login",
initialSavedLogins: [availLogins.emptyXYZ, availLogins.bobABC],
promptArgs: {
oldLogin: "emptyXYZ",
changeLogin: {
username: "alice",
password: "xyz",
},
},
promptTextboxValues: {},
expectedButtonLabel: "Update",
resultDescription: "The existing login just gets a new username",
expectedStorageChange: true,
expectedResultLogins: [
{
username: "alice",
password: "xyz",
},
{
username: "bob",
password: "abc",
},
],
resultCheck() {
is(finalLogins[0].guid, savedLoginsByName.emptyXYZ.guid, "Check guid");
ok(
finalLogins[0].timeLastUsed > savedLoginsByName.emptyXYZ.timeLastUsed,
"Check timeLastUsed of 0th login"
);
},
},
{
name:
"Add username to autosaved login to match an existing usernamed login",
initialSavedLogins: [availLogins.emptyXYZ, availLogins.bobABC],
autoSavedLoginName: "emptyXYZ",
promptArgs: {
oldLogin: "emptyXYZ",
changeLogin: {
username: "bob",
password: availLogins.emptyXYZ.password,
},
},
promptTextboxValues: {},
expectedButtonLabel: "Update",
resultDescription:
"Empty-username login is removed, other login gets the empty-login's password",
expectedStorageChange: true,
expectedResultLogins: [
{
username: "bob",
password: "xyz",
},
],
resultCheck() {
is(finalLogins[0].guid, savedLoginsByName.bobABC.guid, "Check guid");
ok(
finalLogins[0].timeLastUsed > savedLoginsByName.bobABC.timeLastUsed,
"Check timeLastUsed changed"
);
},
},
{
name:
"Add username to non-autosaved login to match an existing usernamed login",
initialSavedLogins: [availLogins.emptyXYZ, availLogins.bobABC],
autoSavedLoginName: "",
promptArgs: {
oldLogin: "emptyXYZ",
changeLogin: {
username: "bob",
password: availLogins.emptyXYZ.password,
},
},
promptTextboxValues: {},
expectedButtonLabel: "Update",
resultDescription: "Multiple login matches, persistData will bail early",
expectedStorageChange: false,
expectedResultLogins: [
{
username: "",
password: "xyz",
},
{
username: "bob",
password: "abc",
},
],
resultCheck() {
is(finalLogins[0].guid, savedLoginsByName.emptyXYZ.guid, "Check guid");
is(
finalLogins[0].timeLastUsed,
savedLoginsByName.emptyXYZ.timeLastUsed,
"Check timeLastUsed didnt change"
);
is(finalLogins[1].guid, savedLoginsByName.bobABC.guid, "Check guid");
is(
finalLogins[1].timeLastUsed,
savedLoginsByName.bobABC.timeLastUsed,
"Check timeLastUsed didnt change"
);
},
},
{
name:
"Username & password changes to an auto-saved login apply to matching usernamed-login",
// when we update an auto-saved login - changing both username & password, is
// the matching login updated and empty-username login removed?
initialSavedLogins: [availLogins.emptyXYZ, availLogins.bobABC],
autoSavedLoginName: "emptyXYZ",
promptArgs: {
oldLogin: "emptyXYZ",
changeLogin: {
username: "bob",
password: "xyz",
},
},
promptTextboxValues: {
// type a new password in the doorhanger
password: "newpassword",
},
expectedButtonLabel: "Update",
resultDescription:
"The empty-username login is removed, other login gets the new password",
expectedStorageChange: true,
expectedResultLogins: [
{
username: "bob",
password: "newpassword",
},
],
resultCheck() {
is(finalLogins[0].guid, savedLoginsByName.bobABC.guid, "Check guid");
ok(
finalLogins[0].timeLastUsed > savedLoginsByName.bobABC.timeLastUsed,
"Check timeLastUsed did change"
);
},
},
{
name:
"Username & password changes to a non-auto-saved login matching usernamed-login",
// when we update a non-auto-saved login - changing both username & password, is
// the matching login updated and empty-username login unchanged?
initialSavedLogins: [availLogins.emptyXYZ, availLogins.bobABC],
autoSavedLoginName: "", // no auto-saved logins for this session
promptArgs: {
oldLogin: "emptyXYZ",
changeLogin: {
username: "bob",
password: "xyz",
},
},
promptTextboxValues: {
// type a new password in the doorhanger
password: "newpassword",
},
expectedButtonLabel: "Update",
resultDescription:
"The empty-username login is not changed, other login gets the new password",
expectedStorageChange: true,
expectedResultLogins: [
{
username: "",
password: "xyz",
},
{
username: "bob",
password: "newpassword",
},
],
resultCheck() {
is(finalLogins[0].guid, savedLoginsByName.emptyXYZ.guid, "Check guid");
is(
finalLogins[0].timeLastUsed,
savedLoginsByName.emptyXYZ.timeLastUsed,
"Check timeLastUsed didn't change"
);
is(
finalLogins[0].timePasswordChanged,
savedLoginsByName.emptyXYZ.timePasswordChanged,
"Check timePasswordChanged didn't change"
);
is(finalLogins[1].guid, savedLoginsByName.bobABC.guid, "Check guid");
ok(
finalLogins[1].timeLastUsed > savedLoginsByName.bobABC.timeLastUsed,
"Check timeLastUsed did change"
);
ok(
finalLogins[1].timePasswordChanged >
savedLoginsByName.bobABC.timePasswordChanged,
"Check timePasswordChanged did change"
);
},
},
{
name: "Remove the username and change password of autosaved login",
initialSavedLogins: [availLogins.bobABC],
autoSavedLoginName: "bobABC",
promptArgs: {
oldLogin: "bobABC",
changeLogin: {
username: "bob",
password: "abc!", // trigger change prompt with a password change
},
},
promptTextboxValues: {
username: "",
},
expectedButtonLabel: "Update",
resultDescription:
"The auto-saved login is updated with new empty-username login and new password",
expectedStorageChange: true,
expectedResultLogins: [
{
username: "",
password: "abc!",
},
],
resultCheck() {
is(finalLogins[0].guid, savedLoginsByName.bobABC.guid, "Check guid");
ok(
finalLogins[0].timeLastUsed > savedLoginsByName.bobABC.timeLastUsed,
"Check timeLastUsed did change"
);
ok(
finalLogins[0].timePasswordChanged >
savedLoginsByName.bobABC.timePasswordChanged,
"Check timePasswordChanged did change"
);
},
},
{
name: "Remove the username and change password of non-autosaved login",
initialSavedLogins: [availLogins.bobABC],
// no autosaved guid
promptArgs: {
oldLogin: "bobABC",
changeLogin: {
username: "bob",
password: "abc!", // trigger change prompt with a password change
},
},
promptTextboxValues: {
username: "",
},
expectedButtonLabel: "Save",
resultDescription:
"A new empty-username login is created with the new password",
expectedStorageChange: true,
expectedResultLogins: [
{
username: "bob",
password: "abc",
},
{
username: "",
password: "abc!",
},
],
resultCheck() {
is(finalLogins[0].guid, savedLoginsByName.bobABC.guid, "Check guid");
is(
finalLogins[0].timeLastUsed,
savedLoginsByName.bobABC.timeLastUsed,
"Check timeLastUsed didn't change"
);
is(
finalLogins[0].timePasswordChanged,
savedLoginsByName.bobABC.timePasswordChanged,
"Check timePasswordChanged didn't change"
);
},
},
{
name: "Remove username from the auto-saved sole login",
initialSavedLogins: [availLogins.bobABC],
autoSavedLoginName: "bobABC",
promptArgs: {
oldLogin: "bobABC",
changeLogin: {
username: "bob",
password: "abc!", // trigger change prompt with a password change
},
},
promptTextboxValues: {
username: "",
password: "abc", // put password back to what it was
},
expectedButtonLabel: "Update",
resultDescription: "The existing login is updated",
expectedStorageChange: true,
expectedResultLogins: [
{
username: "",
password: "abc",
},
],
resultCheck() {
is(finalLogins[0].guid, savedLoginsByName.bobABC.guid, "Check guid");
ok(
finalLogins[0].timeLastUsed > savedLoginsByName.bobABC.timeLastUsed,
"Check timeLastUsed did change"
);
todo_is(
finalLogins[0].timePasswordChanged,
savedLoginsByName.bobABC.timePasswordChanged,
"Check timePasswordChanged didn't change"
);
},
},
{
name: "Remove username from the non-auto-saved sole login",
initialSavedLogins: [availLogins.bobABC],
// no autoSavedLoginGuid
promptArgs: {
oldLogin: "bobABC",
changeLogin: {
username: "bob",
password: "abc!", // trigger change prompt with a password change
},
},
promptTextboxValues: {
username: "",
password: "abc", // put password back to what it was
},
expectedButtonLabel: "Save",
resultDescription: "A new empty-username login is created",
expectedStorageChange: true,
expectedResultLogins: [
{
username: "bob",
password: "abc",
},
{
username: "",
password: "abc",
},
],
resultCheck() {
is(finalLogins[0].guid, savedLoginsByName.bobABC.guid, "Check guid");
is(
finalLogins[0].timeLastUsed,
savedLoginsByName.bobABC.timeLastUsed,
"Check timeLastUsed didn't change"
);
is(
finalLogins[0].timePasswordChanged,
savedLoginsByName.bobABC.timePasswordChanged,
"Check timePasswordChanged didn't change"
);
},
},
];
for (let testData of tests) {
let tmp = {
async [testData.name]() {
await promptToChangePasswordTest(testData);
},
};
add_task(tmp[testData.name]);
}

View File

@ -16,10 +16,10 @@ registerCleanupFunction(
async function cleanup_removeAllLoginsAndResetRecipes() {
await SpecialPowers.popPrefEnv();
LoginTestUtils.clearData();
LoginTestUtils.resetGeneratedPasswordsCache();
Services.logins.removeAllLogins();
clearHttpAuths();
Services.telemetry.clearEvents();
LMP._generatedPasswordsByPrincipalOrigin.clear();
let recipeParent = LoginTestUtils.recipes.getRecipeParent();
if (!recipeParent) {
@ -27,65 +27,9 @@ registerCleanupFunction(
return;
}
await recipeParent.then(recipeParentResult => recipeParentResult.reset());
await cleanupDoorhanger();
let notif;
while ((notif = PopupNotifications.getNotification("password"))) {
notif.remove();
}
}
);
/**
* Compared logins in storage to expected values
*
* @param {array} expectedLogins
* An array of expected login properties
* @return {nsILoginInfo[]} - All saved logins sorted by timeCreated
*/
function verifyLogins(expectedLogins = []) {
let allLogins = Services.logins.getAllLogins();
allLogins.sort((a, b) => a.timeCreated > b.timeCreated);
is(
allLogins.length,
expectedLogins.length,
"Check actual number of logins matches the number of provided expected property-sets"
);
for (let i = 0; i < expectedLogins.length; i++) {
// if the test doesn't care about comparing properties for this login, just pass false/null.
let expected = expectedLogins[i];
if (expected) {
let login = allLogins[i];
if (typeof expected.timesUsed !== "undefined") {
is(login.timesUsed, expected.timesUsed, "Check timesUsed");
}
if (typeof expected.passwordLength !== "undefined") {
is(
login.password.length,
expected.passwordLength,
"Check passwordLength"
);
}
if (typeof expected.username !== "undefined") {
is(login.username, expected.username, "Check username");
}
if (typeof expected.password !== "undefined") {
is(login.password, expected.password, "Check password");
}
if (typeof expected.usedSince !== "undefined") {
ok(login.timeLastUsed > expected.usedSince, "Check timeLastUsed");
}
if (typeof expected.passwordChangedSince !== "undefined") {
ok(
login.timePasswordChanged > expected.passwordChangedSince,
"Check timePasswordChanged"
);
}
}
}
return allLogins;
}
/**
* Loads a test page in `DIRECTORY_URL` which automatically submits to formsubmit.sjs and returns a
* promise resolving with the field values when the optional `aTaskFn` is done.
@ -211,37 +155,6 @@ function getCaptureDoorhanger(
return notification;
}
async function getCaptureDoorhangerThatMayOpen(
aKind,
popupNotifications = PopupNotifications,
browser = null
) {
let notif = getCaptureDoorhanger(aKind, popupNotifications, browser);
if (notif && !notif.dismissed) {
if (popupNotifications.panel.state !== "open") {
await BrowserTestUtils.waitForEvent(
popupNotifications.panel,
"popupshown"
);
}
}
return notif;
}
function getDoorhangerButton(aPopup, aButtonIndex) {
let notifications = aPopup.owner.panel.children;
ok(notifications.length > 0, "at least one notification displayed");
ok(true, notifications.length + " notification(s)");
let notification = notifications[0];
if (aButtonIndex == "button") {
return notification.button;
} else if (aButtonIndex == "secondaryButton") {
return notification.secondaryButton;
}
return notification.menupopup.querySelectorAll("menuitem")[aButtonIndex];
}
/**
* Clicks the specified popup notification button.
*
@ -252,27 +165,23 @@ function getDoorhangerButton(aPopup, aButtonIndex) {
function clickDoorhangerButton(aPopup, aButtonIndex) {
ok(true, "Looking for action at index " + aButtonIndex);
let button = getDoorhangerButton(aPopup, aButtonIndex);
let notifications = aPopup.owner.panel.children;
ok(notifications.length > 0, "at least one notification displayed");
ok(true, notifications.length + " notification(s)");
let notification = notifications[0];
if (aButtonIndex == "button") {
ok(true, "Triggering main action");
notification.button.doCommand();
} else if (aButtonIndex == "secondaryButton") {
ok(true, "Triggering secondary action");
notification.secondaryButton.doCommand();
} else {
ok(true, "Triggering menuitem # " + aButtonIndex);
notification.menupopup
.querySelectorAll("menuitem")
[aButtonIndex].doCommand();
}
button.doCommand();
}
async function cleanupDoorhanger(notif) {
let PN = notif ? notif.owner : PopupNotifications;
if (notif) {
notif.remove();
}
let promiseHidden = PN.isPanelOpen
? BrowserTestUtils.waitForEvent(PN.panel, "popuphidden")
: Promise.resolve;
PN.panel.hidePopup();
await promiseHidden;
}
/**
@ -300,54 +209,6 @@ async function checkDoorhangerUsernamePassword(username, password) {
);
}
/**
* Change the doorhanger's username and password input values.
*
* @param {object} newValues
* named values to update
* @param {string} [newValues.password = undefined]
* An optional string value to replace whatever is in the password field
* @param {string} [newValues.username = undefined]
* An optional string value to replace whatever is in the username field
*/
async function updateDoorhangerInputValues(newValues) {
let { panel } = PopupNotifications;
is(panel.state, "open", "Check the doorhanger is already open");
let notifElem = panel.childNodes[0];
// Note: setUserInput does not reliably dispatch input events from chrome elements?
async function setInputValue(target, value) {
info(`setInputValue: on target: ${target.id}, value: ${value}`);
target.focus();
await EventUtils.synthesizeKey("KEY_End");
while (target.value.length) {
await EventUtils.synthesizeKey("KEY_Backspace");
}
await EventUtils.sendString(value);
await EventUtils.synthesizeKey("VK_TAB");
return Promise.resolve();
}
let passwordField = notifElem.querySelector(
"#password-notification-password"
);
let usernameField = notifElem.querySelector(
"#password-notification-username"
);
if (typeof newValues.password !== "undefined") {
if (passwordField.value !== newValues.password) {
await setInputValue(passwordField, newValues.password);
}
}
if (typeof newValues.username !== "undefined") {
if (usernameField.value !== newValues.username) {
await setInputValue(usernameField, newValues.username);
}
}
}
// End popup notification (doorhanger) functions //
async function waitForPasswordManagerDialog(openingFunc) {
@ -510,27 +371,9 @@ async function doFillGeneratedPasswordContextMenuItem(browser, passwordInput) {
await ContentTaskUtils.waitForEvent(input, "input");
}
);
let messagePromise = new Promise(resolve => {
const eventName = "PasswordManager:onGeneratedPasswordFilledOrEdited";
browser.messageManager.addMessageListener(eventName, function mgsHandler(
msg
) {
if (msg.target != browser) {
return;
}
browser.messageManager.removeMessageListener(eventName, mgsHandler);
info(
"doFillGeneratedPasswordContextMenuItem: Got onGeneratedPasswordFilledOrEdited, resolving"
);
// allow LMP to handle the message, then resolve
SimpleTest.executeSoon(resolve);
});
});
EventUtils.synthesizeMouseAtCenter(generatedPasswordItem, {});
info(
"doFillGeneratedPasswordContextMenuItem: Waiting for content input event"
);
generatedPasswordItem.doCommand();
info("Waiting for input event");
await passwordChangedPromise;
await messagePromise;
document.getElementById("contentAreaContextMenu").hidePopup();
}