mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 00:05:36 +00:00
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:
parent
12ea9cfff0
commit
1d06495330
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -108,4 +108,3 @@ support-files =
|
||||
subtst_privbrowsing_1.html
|
||||
form_password_change.html
|
||||
skip-if = fission
|
||||
[browser_promptToChangePassword.js]
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -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);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -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");
|
||||
|
@ -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"
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -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);
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -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]);
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user