Backed out 14 changesets (bug 1824112) for causing mochitest failures in test_autocomplete_password_generation.html CLOSED TREE

Backed out changeset baf6c4c08d47 (bug 1824112)
Backed out changeset 999f8503465f (bug 1824112)
Backed out changeset 4830f780be1e (bug 1824112)
Backed out changeset 73b00f93c2e2 (bug 1824112)
Backed out changeset a53067121b90 (bug 1824112)
Backed out changeset f5d52901dfec (bug 1824112)
Backed out changeset 8b31247f3c94 (bug 1824112)
Backed out changeset 990365a7418d (bug 1824112)
Backed out changeset c3be4f0b5337 (bug 1824112)
Backed out changeset f23b0ce08de1 (bug 1824112)
Backed out changeset 526d53b4a35f (bug 1824112)
Backed out changeset b8010f604733 (bug 1824112)
Backed out changeset 602e53d29d80 (bug 1824112)
Backed out changeset 50e0b57bd30d (bug 1824112)
This commit is contained in:
Noemi Erli 2023-05-08 10:45:21 +03:00
Родитель 771ec34f2e
Коммит d7f52efd60
96 изменённых файлов: 2232 добавлений и 1977 удалений

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

@ -21,7 +21,7 @@ add_task(async function test_showLoginItemErrors() {
"user2",
"pass2"
);
LOGIN_TO_UPDATE = await Services.logins.addLoginAsync(LOGIN_TO_UPDATE);
LOGIN_TO_UPDATE = Services.logins.addLogin(LOGIN_TO_UPDATE);
EXPECTED_ERROR_MESSAGE = "This login already exists.";
const LOGIN_UPDATES = {
origin: "https://example.com",

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

@ -6,13 +6,13 @@ add_setup(async function() {
"passwordmgr-storage-changed",
(_, data) => data == "addLogin"
);
TEST_LOGIN1 = await Services.logins.addLoginAsync(TEST_LOGIN1);
TEST_LOGIN1 = Services.logins.addLogin(TEST_LOGIN1);
await storageChangedPromised;
storageChangedPromised = TestUtils.topicObserved(
"passwordmgr-storage-changed",
(_, data) => data == "addLogin"
);
TEST_LOGIN2 = await Services.logins.addLoginAsync(TEST_LOGIN2);
TEST_LOGIN2 = Services.logins.addLogin(TEST_LOGIN2);
await storageChangedPromised;
let tabOpenedPromise = BrowserTestUtils.waitForNewTab(
gBrowser,

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

@ -54,12 +54,17 @@ let TEST_LOGIN3 = new nsLoginInfo(
TEST_LOGIN3.QueryInterface(Ci.nsILoginMetaInfo).timePasswordChanged = 123456;
async function addLogin(login) {
const result = await Services.logins.addLoginAsync(login);
let storageChangedPromised = TestUtils.topicObserved(
"passwordmgr-storage-changed",
(_, data) => data == "addLogin"
);
login = Services.logins.addLogin(login);
await storageChangedPromised;
registerCleanupFunction(() => {
let matchData = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
Ci.nsIWritablePropertyBag2
);
matchData.setPropertyAsAUTF8String("guid", result.guid);
matchData.setPropertyAsAUTF8String("guid", login.guid);
let logins = Services.logins.searchLogins(matchData);
if (!logins.length) {
@ -71,7 +76,7 @@ async function addLogin(login) {
// matches the login that it will be removing.
Services.logins.removeLogin(logins[0]);
});
return result;
return login;
}
let EXPECTED_BREACH = null;

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

@ -110,7 +110,7 @@ const LOGIN_WITH_NON_STANDARD_URI = LoginTestUtils.testData.formLogin({
});
add_task(async function test_notBreachedLogin() {
await Services.logins.addLoginAsync(NOT_BREACHED_LOGIN);
Services.logins.addLogin(NOT_BREACHED_LOGIN);
const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
[NOT_BREACHED_LOGIN],
TEST_BREACHES
@ -123,7 +123,7 @@ add_task(async function test_notBreachedLogin() {
});
add_task(async function test_breachedLogin() {
await Services.logins.addLoginAsync(BREACHED_LOGIN);
Services.logins.addLogin(BREACHED_LOGIN);
const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
[NOT_BREACHED_LOGIN, BREACHED_LOGIN],
TEST_BREACHES
@ -141,7 +141,7 @@ add_task(async function test_breachedLogin() {
});
add_task(async function test_breachedLoginAfterCrashingUriLogin() {
await Services.logins.addLoginAsync(CRASHING_URI_LOGIN);
Services.logins.addLogin(CRASHING_URI_LOGIN);
const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
[CRASHING_URI_LOGIN, BREACHED_LOGIN],
@ -160,7 +160,7 @@ add_task(async function test_breachedLoginAfterCrashingUriLogin() {
});
add_task(async function test_notBreachedSubdomain() {
await Services.logins.addLoginAsync(NOT_BREACHED_SUBDOMAIN_LOGIN);
Services.logins.addLogin(NOT_BREACHED_SUBDOMAIN_LOGIN);
const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
[NOT_BREACHED_LOGIN, NOT_BREACHED_SUBDOMAIN_LOGIN],
@ -174,7 +174,7 @@ add_task(async function test_notBreachedSubdomain() {
});
add_task(async function test_breachedSubdomain() {
await Services.logins.addLoginAsync(BREACHED_SUBDOMAIN_LOGIN);
Services.logins.addLogin(BREACHED_SUBDOMAIN_LOGIN);
const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
[NOT_BREACHED_SUBDOMAIN_LOGIN, BREACHED_SUBDOMAIN_LOGIN],
@ -188,9 +188,7 @@ add_task(async function test_breachedSubdomain() {
});
add_task(async function test_breachedSiteWithoutPasswords() {
await Services.logins.addLoginAsync(
LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS
);
Services.logins.addLogin(LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS);
const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
[LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS],
@ -254,7 +252,7 @@ add_task(async function test_newBreachAfterDismissal() {
});
add_task(async function test_ExceptionsThrownByNonStandardURIsAreCaught() {
await Services.logins.addLoginAsync(LOGIN_WITH_NON_STANDARD_URI);
Services.logins.addLogin(LOGIN_WITH_NON_STANDARD_URI);
const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
[LOGIN_WITH_NON_STANDARD_URI, BREACHED_LOGIN],

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

@ -10,7 +10,7 @@ const NEW_HOST = "http://mozilla.com";
const FXA_HOST = "chrome://FirefoxAccounts";
function checkLoginExists(host, shouldExist) {
const logins = Services.logins.findLogins(host, "", null);
let logins = Services.logins.findLogins(host, "", null);
equal(
logins.length,
shouldExist ? 1 : 0,
@ -18,7 +18,7 @@ function checkLoginExists(host, shouldExist) {
);
}
async function addLogin(host, timestamp) {
function addLogin(host, timestamp) {
checkLoginExists(host, false);
let login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(
Ci.nsILoginInfo
@ -26,15 +26,15 @@ async function addLogin(host, timestamp) {
login.init(host, "", null, LOGIN_USERNAME, LOGIN_PASSWORD);
login.QueryInterface(Ci.nsILoginMetaInfo);
login.timePasswordChanged = timestamp;
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
checkLoginExists(host, true);
}
async function setupPasswords() {
Services.logins.removeAllUserFacingLogins();
await addLogin(FXA_HOST, REFERENCE_DATE);
await addLogin(NEW_HOST, REFERENCE_DATE);
await addLogin(OLD_HOST, REFERENCE_DATE - 10000);
addLogin(FXA_HOST, REFERENCE_DATE);
addLogin(NEW_HOST, REFERENCE_DATE);
addLogin(OLD_HOST, REFERENCE_DATE - 10000);
}
add_task(async function testPasswords() {
@ -49,7 +49,7 @@ add_task(async function testPasswords() {
});
}
const extension = ExtensionTestUtils.loadExtension({
let extension = ExtensionTestUtils.loadExtension({
background,
manifest: {
permissions: ["browsingData"],

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

@ -40,20 +40,18 @@ class TestFirefoxRefresh(MarionetteTestCase):
_expectedURLs = ["about:robots", "about:mozilla"]
def savePassword(self):
self.runAsyncCode(
self.runCode(
"""
let [username, password, resolve] = arguments;
let myLogin = new global.LoginInfo(
"test.marionette.mozilla.com",
"http://test.marionette.mozilla.com/some/form/",
null,
username,
password,
arguments[0],
arguments[1],
"username",
"password"
);
Services.logins.addLoginAsync(myLogin)
.then(() => resolve(false), resolve);
Services.logins.addLogin(myLogin)
""",
script_args=(self._username, self._password),
)

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

@ -104,12 +104,12 @@ var loginCrypto;
var dbConn;
async function promiseSetPassword(login) {
const encryptedString = await loginCrypto.encryptData(
let encryptedString = await loginCrypto.encryptData(
login.password,
login.version
);
info(`promiseSetPassword: ${encryptedString}`);
const passwordValue = new Uint8Array(
let passwordValue = new Uint8Array(
loginCrypto.stringToArray(encryptedString)
);
return dbConn.execute(
@ -177,7 +177,7 @@ function checkLoginsAreEqual(passwordManagerLogin, chromeLogin, id) {
}
function generateDifferentLogin(login) {
const newLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(
let newLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(
Ci.nsILoginInfo
);
@ -206,13 +206,13 @@ add_task(async function setup() {
// would block the test from finishing if Chrome has already created a matching
// Keychain entry. This allows us to still exercise the keychain lookup code.
// The mock encryption passphrase is used when the Keychain item isn't found.
const mockMacOSKeychain = {
let mockMacOSKeychain = {
passphrase: "bW96aWxsYWZpcmVmb3g=",
serviceName: "TESTING Chrome Safe Storage",
accountName: "TESTING Chrome",
};
if (AppConstants.platform == "macosx") {
const { ChromeMacOSLoginCrypto } = ChromeUtils.importESModule(
let { ChromeMacOSLoginCrypto } = ChromeUtils.importESModule(
"resource:///modules/ChromeMacOSLoginCrypto.sys.mjs"
);
loginCrypto = new ChromeMacOSLoginCrypto(
@ -230,7 +230,7 @@ add_task(async function setup() {
"Login Data",
];
} else if (AppConstants.platform == "win") {
const { ChromeWindowsLoginCrypto } = ChromeUtils.importESModule(
let { ChromeWindowsLoginCrypto } = ChromeUtils.importESModule(
"resource:///modules/ChromeWindowsLoginCrypto.sys.mjs"
);
loginCrypto = new ChromeWindowsLoginCrypto("Chrome");
@ -246,18 +246,18 @@ add_task(async function setup() {
} else {
throw new Error("Not implemented");
}
const dirSvcFile = do_get_file(dirSvcPath);
let dirSvcFile = do_get_file(dirSvcPath);
registerFakePath(pathId, dirSvcFile);
info(PathUtils.join(dirSvcFile.path, ...profilePathSegments));
const loginDataFilePath = PathUtils.join(
let loginDataFilePath = PathUtils.join(
dirSvcFile.path,
...profilePathSegments
);
dbConn = await Sqlite.openConnection({ path: loginDataFilePath });
if (AppConstants.platform == "macosx") {
const migrator = await MigrationUtils.getMigrator("chrome");
let migrator = await MigrationUtils.getMigrator("chrome");
Object.assign(migrator, {
_keychainServiceName: mockMacOSKeychain.serviceName,
_keychainAccountName: mockMacOSKeychain.accountName,
@ -275,11 +275,11 @@ add_task(async function setup() {
});
add_task(async function test_importIntoEmptyDB() {
for (const login of TEST_LOGINS) {
for (let login of TEST_LOGINS) {
await promiseSetPassword(login);
}
const migrator = await MigrationUtils.getMigrator("chrome");
let migrator = await MigrationUtils.getMigrator("chrome");
Assert.ok(
await migrator.isSourceAvailable(),
"Sanity check the source exists"
@ -315,7 +315,7 @@ add_task(async function test_importIntoEmptyDB() {
// Test that existing logins for the same primary key don't get overwritten
add_task(async function test_importExistingLogins() {
const migrator = await MigrationUtils.getMigrator("chrome");
let migrator = await MigrationUtils.getMigrator("chrome");
Assert.ok(
await migrator.isSourceAvailable(),
"Sanity check the source exists"
@ -329,7 +329,7 @@ add_task(async function test_importExistingLogins() {
"There are no logins after removing all of them"
);
const newLogins = [];
let newLogins = [];
// Create 3 new logins that are different but where the key properties are still the same.
for (let i = 0; i < 3; i++) {

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

@ -12,11 +12,11 @@ const { AboutProtectionsParent } = ChromeUtils.importESModule(
const ABOUT_LOGINS_URL = "about:logins";
add_task(async function testNoLoginsLockwiseCardUI() {
const tab = await BrowserTestUtils.openNewForegroundTab({
let tab = await BrowserTestUtils.openNewForegroundTab({
url: "about:protections",
gBrowser,
});
const aboutLoginsPromise = BrowserTestUtils.waitForNewTab(
let aboutLoginsPromise = BrowserTestUtils.waitForNewTab(
gBrowser,
ABOUT_LOGINS_URL
);
@ -76,18 +76,18 @@ add_task(async function testNoLoginsLockwiseCardUI() {
);
savePasswordsButton.click();
});
const loginsTab = await aboutLoginsPromise;
let loginsTab = await aboutLoginsPromise;
info("about:logins was successfully opened in a new tab");
gBrowser.removeTab(loginsTab);
gBrowser.removeTab(tab);
});
add_task(async function testLockwiseCardUIWithLogins() {
const tab = await BrowserTestUtils.openNewForegroundTab({
let tab = await BrowserTestUtils.openNewForegroundTab({
url: "about:protections",
gBrowser,
});
const aboutLoginsPromise = BrowserTestUtils.waitForNewTab(
let aboutLoginsPromise = BrowserTestUtils.waitForNewTab(
gBrowser,
ABOUT_LOGINS_URL
);
@ -95,7 +95,7 @@ add_task(async function testLockwiseCardUIWithLogins() {
info(
"Add a login and check that lockwise card content for a logged in user is displayed correctly"
);
await Services.logins.addLoginAsync(TEST_LOGIN1);
Services.logins.addLogin(TEST_LOGIN1);
await BrowserTestUtils.reloadTab(tab);
await SpecialPowers.spawn(tab.linkedBrowser, [], async function() {
@ -172,14 +172,14 @@ add_task(async function testLockwiseCardUIWithLogins() {
);
managePasswordsButton.click();
});
const loginsTab = await aboutLoginsPromise;
let loginsTab = await aboutLoginsPromise;
info("about:logins was successfully opened in a new tab");
gBrowser.removeTab(loginsTab);
info(
"Add another login and check that the scanned text about stored logins is updated after reload."
);
await Services.logins.addLoginAsync(TEST_LOGIN2);
Services.logins.addLogin(TEST_LOGIN2);
await BrowserTestUtils.reloadTab(tab);
await SpecialPowers.spawn(tab.linkedBrowser, [], async function() {
@ -204,11 +204,11 @@ add_task(async function testLockwiseCardUIWithBreachedLogins() {
info(
"Add a breached login and test that the lockwise scanned text is displayed correctly"
);
const tab = await BrowserTestUtils.openNewForegroundTab({
let tab = await BrowserTestUtils.openNewForegroundTab({
url: "about:protections",
gBrowser,
});
await Services.logins.addLoginAsync(TEST_LOGIN1);
Services.logins.addLogin(TEST_LOGIN1);
info("Mock monitor data with a breached login to test the Lockwise UI");
AboutProtectionsParent.setTestOverride(
@ -261,7 +261,7 @@ add_task(async function testLockwiseCardUIWithBreachedLogins() {
});
add_task(async function testLockwiseCardPref() {
const tab = await BrowserTestUtils.openNewForegroundTab({
let tab = await BrowserTestUtils.openNewForegroundTab({
url: "about:protections",
gBrowser,
});

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

@ -18,14 +18,14 @@ const mockMonitorData = {
};
add_task(async function() {
const tab = await BrowserTestUtils.openNewForegroundTab({
let tab = await BrowserTestUtils.openNewForegroundTab({
url: "about:protections",
gBrowser,
});
await BrowserTestUtils.reloadTab(tab);
const monitorCardEnabled = Services.prefs.getBoolPref(
let monitorCardEnabled = Services.prefs.getBoolPref(
"browser.contentblocking.report.monitor.enabled"
);
@ -39,7 +39,7 @@ add_task(async function() {
info(
"Check that the correct content is displayed for users with monitor data."
);
await Services.logins.addLoginAsync(TEST_LOGIN1);
Services.logins.addLogin(TEST_LOGIN1);
AboutProtectionsParent.setTestOverride(mockGetMonitorData(mockMonitorData));
await BrowserTestUtils.reloadTab(tab);

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

@ -207,7 +207,7 @@ add_task(async function checkTelemetryClickEvents() {
});
// Add user logins.
await Services.logins.addLoginAsync(TEST_LOGIN1);
Services.logins.addLogin(TEST_LOGIN1);
await BrowserTestUtils.reloadTab(tab);
await SpecialPowers.spawn(tab.linkedBrowser, [], async function() {
const managePasswordsButton = await ContentTaskUtils.waitForCondition(

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

@ -190,7 +190,7 @@ const heuristics = [
Ci.nsILoginInfo,
"init"
);
await Services.logins.addLoginAsync(
Services.logins.addLogin(
new LoginInfo(COM_ORIGIN, "", null, "username", "password", "", "")
);

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

@ -562,7 +562,7 @@ LoginManagerStorage.prototype = {
if (existingLogins.length) {
Services.logins.modifyLogin(existingLogins[0], login);
} else {
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
}
log.trace("finished write of user data to the login manager");
} catch (ex) {

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

@ -305,7 +305,7 @@ add_task(async function test_uidMigration() {
"", // aUsernameField
""
); // aPasswordField
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
// ensure we read it.
let storage = new LoginManagerStorage();

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

@ -346,7 +346,7 @@ PasswordStore.prototype = {
"formSubmitURL: " +
JSON.stringify(login.formActionOrigin)
);
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
},
async remove(record) {

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

@ -143,7 +143,7 @@ add_task(async function test_passwords_change_during_sync() {
"",
""
);
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
await engine._tracker.asyncObserver.promiseObserversComplete();
}
};

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

@ -45,7 +45,7 @@ add_task(async function test_ignored_fields() {
enableValidationPrefs();
let login = await Services.logins.addLoginAsync(
let login = Services.logins.addLogin(
new LoginInfo(
"https://example.com",
"",
@ -97,7 +97,7 @@ add_task(async function test_ignored_sync_credentials() {
engine._tracker.start();
try {
let login = await Services.logins.addLoginAsync(
let login = Services.logins.addLogin(
new LoginInfo(
FXA_PWDMGR_HOST,
null,
@ -146,7 +146,7 @@ add_task(async function test_password_engine() {
"",
""
);
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
let logins = Services.logins.findLogins("https://example.com", "", "");
equal(logins.length, 1, "Should find new login in login manager");
@ -181,7 +181,7 @@ add_task(async function test_password_engine() {
"",
""
);
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
let props = new PropertyBag();
let localPasswordChangeTime = Date.now() - 1 * 60 * 60 * 24 * 1000;

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

@ -39,7 +39,7 @@ add_task(async function test_tracking() {
};
recordNum++;
let login = store._nsLoginInfoFromRecord(record);
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
await tracker.asyncObserver.promiseObserversComplete();
}
@ -126,7 +126,7 @@ add_task(async function test_removeAllLogins() {
};
recordNum++;
let login = store._nsLoginInfoFromRecord(record);
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
await tracker.asyncObserver.promiseObserversComplete();
}
try {

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

@ -99,7 +99,6 @@ Password.prototype = {
this.props.usernameField,
this.props.passwordField
);
// TODO: use `addLoginAsync` instead, see https://bugzilla.mozilla.org/show_bug.cgi?id=1829396
Services.logins.addLogin(login);
login.QueryInterface(Ci.nsILoginMetaInfo);
return login.guid;

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

@ -20,7 +20,7 @@ add_task(async function test_principal_downloads() {
usernameField: "field_username",
passwordField: "field_password",
});
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
Assert.equal(countLogins(URL), 1);
@ -57,7 +57,7 @@ add_task(async function test_all() {
usernameField: "field_username",
passwordField: "field_password",
});
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
Assert.equal(countLogins(URL), 1);

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

@ -107,7 +107,7 @@ function check_disabled_host(aHost, aIsDisabled) {
* @param aHost
* The host to add the login for.
*/
async function add_login(aHost) {
function add_login(aHost) {
check_login_exists(aHost, false);
let login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(
Ci.nsILoginInfo
@ -121,7 +121,7 @@ async function add_login(aHost) {
LOGIN_USERNAME_FIELD,
LOGIN_PASSWORD_FIELD
);
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
check_login_exists(aHost, true);
}
@ -312,21 +312,21 @@ async function test_login_manager_disabled_hosts_not_cleared_with_uri_contains_d
async function test_login_manager_logins_cleared_with_direct_match() {
const TEST_HOST = "http://mozilla.org";
await add_login(TEST_HOST);
add_login(TEST_HOST);
await ForgetAboutSite.removeDataFromDomain("mozilla.org");
check_login_exists(TEST_HOST, true);
}
async function test_login_manager_logins_cleared_with_subdomain() {
const TEST_HOST = "http://www.mozilla.org";
await add_login(TEST_HOST);
add_login(TEST_HOST);
await ForgetAboutSite.removeDataFromDomain("mozilla.org");
check_login_exists(TEST_HOST, true);
}
async function test_login_manager_logins_not_cleared_with_uri_contains_domain() {
const TEST_HOST = "http://ilovemozilla.org";
await add_login(TEST_HOST);
add_login(TEST_HOST);
await ForgetAboutSite.removeDataFromDomain("mozilla.org");
check_login_exists(TEST_HOST, true);

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

@ -303,7 +303,6 @@ LoginManager.prototype = {
/**
* Add a new login to login storage.
* @deprecated: use `addLoginAsync` instead.
*/
addLogin(login) {
this._checkLogin(login);
@ -319,40 +318,8 @@ LoginManager.prototype = {
if (matchingLogin) {
throw lazy.LoginHelper.createLoginAlreadyExistsError(matchingLogin.guid);
}
lazy.log.debug("addLogin is DEPRECATED, please use addLoginAsync instead.");
return this._storage.addLogin(login);
},
/**
* Add a new login to login storage.
*/
async addLoginAsync(login) {
this._checkLogin(login);
const { origin, formActionOrigin, httpRealm } = login;
const existingLogins = this.findLogins(origin, formActionOrigin, httpRealm);
const matchingLogin = existingLogins.find(l => login.matches(l, true));
if (matchingLogin) {
throw lazy.LoginHelper.createLoginAlreadyExistsError(matchingLogin.guid);
}
const crypto = Cc["@mozilla.org/login-manager/crypto/SDR;1"].getService(
Ci.nsILoginManagerCrypto
);
const plaintexts = [login.username, login.password];
const [username, password] = await crypto.encryptMany(plaintexts);
const { username: plaintextUsername, password: plaintextPassword } = login;
login.username = username;
login.password = password;
lazy.log.debug("Adding login");
return this._storage.addLogin(
login,
true,
plaintextUsername,
plaintextPassword
);
return this._storage.addLogin(login);
},
async addLogins(logins) {

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

@ -1414,9 +1414,7 @@ export class LoginManagerParent extends JSWindowActorParent {
existingLogin.password = formLogin.password;
} else if (!autoSavedLogin) {
lazy.log("Auto-saving new login with empty username.");
existingLogin = await Services.logins.addLoginAsync(
formLoginWithoutUsername
);
existingLogin = Services.logins.addLogin(formLoginWithoutUsername);
// Remember the GUID where we saved the generated password so we can update
// the login if the user later edits the generated password.
generatedPW.storageGUID = existingLogin.guid;

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

@ -44,19 +44,6 @@ interface nsILoginManager : nsISupports {
*/
nsILoginInfo addLogin(in nsILoginInfo aLogin);
/**
* Like addLogin, but asynchronous.
*
* @param aLogin
* The login to be added.
* @return A promise which resolves with a cloned login with the guid set.
*
* Default values for each login's nsILoginMetaInfo properties will be
* created. However, if the caller specifies non-default values, they will
* be used instead.
*/
Promise addLoginAsync(in nsILoginInfo aLogin);
/**
* Like addLogin, but asynchronous and for many logins.
*

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

@ -64,7 +64,13 @@ export const LoginTestUtils = {
username,
password,
});
return Services.logins.addLoginAsync(login);
let storageChangedPromised = TestUtils.topicObserved(
"passwordmgr-storage-changed",
(_, data) => data == "addLogin"
);
Services.logins.addLogin(login);
let [savedLogin] = await storageChangedPromised;
return savedLogin;
},
async modifyLogin(oldLogin, newLogin) {

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

@ -7,14 +7,14 @@ add_setup(async function() {
username: "username1",
password: "password1",
});
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
login = LoginTestUtils.testData.formLogin({
origin: "https://example.org",
formActionOrigin: "https://example.org",
username: "username2",
password: "password2",
});
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
});
// Verify that the autocomplete popup opens when the username field in autofocused.

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

@ -22,7 +22,8 @@ add_setup(async () => {
password: "password2",
});
await Services.logins.addLogins([login1, login2]);
Services.logins.addLogin(login1);
Services.logins.addLogin(login2);
});
add_task(

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

@ -29,7 +29,9 @@ add_task(async function test_initialize() {
Services.prefs.clearUserPref("signon.showAutoCompleteFooter");
});
await Services.logins.addLogins(loginList());
for (let login of loginList()) {
Services.logins.addLogin(login);
}
});
add_task(async function test_autocomplete_footer_onclick() {

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

@ -30,7 +30,7 @@ add_setup(async function() {
username: "username",
password: "password",
});
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
LoginTestUtils.primaryPassword.enable();
registerCleanupFunction(function() {
@ -82,10 +82,10 @@ add_task(async function test_mpAutocompleteUIBusy() {
let win = await BrowserTestUtils.openNewBrowserWindow();
Services.tm.dispatchToMainThread(async () => {
Services.tm.dispatchToMainThread(() => {
try {
// Trigger a MP prompt in the new window by saving a login
await Services.logins.addLoginAsync(LoginTestUtils.testData.formLogin());
Services.logins.addLogin(LoginTestUtils.testData.formLogin());
} catch (e) {
// Handle throwing from MP cancellation
}

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

@ -35,7 +35,7 @@ add_setup(async function() {
username: "user1",
password: "pass1",
});
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
});
testUrlsWithForm.forEach(testUrl => {

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

@ -2,19 +2,20 @@ const TEST_URL_PATH =
"://example.org/browser/toolkit/components/passwordmgr/test/browser/";
add_setup(async function() {
const login1 = LoginTestUtils.testData.formLogin({
let login = LoginTestUtils.testData.formLogin({
origin: "http://example.org",
formActionOrigin: "http://example.org",
username: "username",
password: "password",
});
const login2 = LoginTestUtils.testData.formLogin({
Services.logins.addLogin(login);
login = LoginTestUtils.testData.formLogin({
origin: "http://example.org",
formActionOrigin: "http://example.com",
username: "username",
password: "password",
});
await Services.logins.addLogins([login1, login2]);
Services.logins.addLogin(login);
await SpecialPowers.pushPrefEnv({
set: [["signon.autofillForms.http", false]],
});

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

@ -31,7 +31,7 @@ add_task(async function test() {
"form-basic-username",
"form-basic-password"
);
login = await Services.logins.addLoginAsync(login);
login = Services.logins.addLogin(login);
Assert.equal(
login.timesUsed,
1,

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

@ -26,7 +26,9 @@ add_task(async function test_initialize() {
Services.prefs.clearUserPref("signon.schemeUpgrades");
Services.prefs.clearUserPref("signon.usernameOnlyForm.enabled");
});
await Services.logins.addLogins(loginList());
for (let login of loginList()) {
Services.logins.addLogin(login);
}
});
/**

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

@ -22,7 +22,9 @@ add_task(async function test_initialize() {
autocompleteUnexpectedPopupShowing
);
});
await Services.logins.addLogins(loginList());
for (let login of loginList()) {
Services.logins.addLogin(login);
}
autocompletePopup.addEventListener(
"popupshowing",
autocompleteUnexpectedPopupShowing

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

@ -260,7 +260,7 @@ add_task(async function fill_generated_password_with_matching_logins() {
"passwordmgr-storage-changed",
(_, data) => data == "addLogin"
);
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
await storageChangedPromised;
let formFilled = listenForTestNotification("FormProcessed");

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

@ -21,7 +21,9 @@ add_task(async function test_initialize() {
Services.prefs.clearUserPref("signon.autofillForms");
Services.prefs.clearUserPref("signon.schemeUpgrades");
});
await Services.logins.addLogins(loginList());
for (let login of loginList()) {
Services.logins.addLogin(login);
}
});
/**

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

@ -82,10 +82,10 @@ add_task(
let storageUpdatePromise = TestUtils.topicObserved(
"password-storage-updated"
);
await Services.logins.addLoginAsync(login1);
Services.logins.addLogin(login1);
Assert.ok(true, "added login1");
await loginStoreExists();
await Services.logins.addLoginAsync(fxaKey);
Services.logins.addLogin(fxaKey);
Assert.ok(true, "added fxaKey");
await loginBackupExists();
Assert.ok(true, "logins-backup.json now exists");
@ -123,12 +123,12 @@ add_task(async function test_deleteLoginsBackup_removeAllUserFacingLogins() {
"password-storage-updated"
);
info("Add a login to create logins.json");
await Services.logins.addLoginAsync(login1);
Services.logins.addLogin(login1);
await loginStoreExists();
Assert.ok(true, "logins.json now exists");
info("Add a second login to create logins-backup.json");
await Services.logins.addLoginAsync(login2);
Services.logins.addLogin(login2);
await loginBackupExists();
info("logins-backup.json now exists");
@ -166,11 +166,11 @@ add_task(async function test_deleteLoginsBackup_removeAllLogins() {
"password-storage-updated"
);
info("Add a login to create logins.json");
await Services.logins.addLoginAsync(login1);
Services.logins.addLogin(login1);
Assert.ok(true, "added login1");
await loginStoreExists();
Assert.ok(true, "logins.json now exists");
await Services.logins.addLoginAsync(login2);
Services.logins.addLogin(login2);
Assert.ok(true, "added login2");
await loginBackupExists();
info("logins-backup.json now exists");
@ -193,9 +193,9 @@ add_task(async function test_deleteLoginsBackup_removeAllLogins() {
info("Testing the removeAllLogins() case when FxA key is present");
storageUpdatePromise = TestUtils.topicObserved("password-storage-updated");
await Services.logins.addLoginAsync(login1);
Services.logins.addLogin(login1);
await loginStoreExists();
await Services.logins.addLoginAsync(fxaKey);
Services.logins.addLogin(fxaKey);
await loginBackupExists();
info("logins-backup.json now exists");
await storageUpdatePromise;
@ -225,9 +225,9 @@ add_task(async function test_deleteLoginsBackup_removeLogin() {
let storageUpdatePromise = TestUtils.topicObserved(
"password-storage-updated"
);
await Services.logins.addLoginAsync(login1);
Services.logins.addLogin(login1);
await loginStoreExists();
await Services.logins.addLoginAsync(login2);
Services.logins.addLogin(login2);
await loginBackupExists();
info("logins-backup.json now exists");
@ -255,9 +255,9 @@ add_task(async function test_deleteLoginsBackup_removeLogin() {
info("Testing the removeLogin() case when there is a saved fxa key");
info("Adding two logins: one user facing and the fxa key");
storageUpdatePromise = TestUtils.topicObserved("password-storage-updated");
await Services.logins.addLoginAsync(login1);
Services.logins.addLogin(login1);
await loginStoreExists();
await Services.logins.addLoginAsync(fxaKey);
Services.logins.addLogin(fxaKey);
await loginBackupExists();
info("logins-backup.json now exists");

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

@ -138,8 +138,8 @@ async function _setPrefs() {
});
}
async function _addSavedLogins(logins) {
let loginsData = logins.map(({ username }) =>
function _addSavedLogin(username) {
Services.logins.addLogin(
LoginTestUtils.testData.formLogin({
origin: "https://example.com",
formActionOrigin: "https://example.com",
@ -147,7 +147,6 @@ async function _addSavedLogins(logins) {
password: "Saved login passwords not used in this test",
})
);
await Services.logins.addLogins(loginsData);
}
async function _clickDropmarker(document, notificationElement) {
@ -181,9 +180,12 @@ add_task(async function test_edit_password() {
Services.logins.removeAllUserFacingLogins();
// Create the pre-existing logins when needed.
info("Adding any saved logins");
if (testCase.savedLogins) {
info("Adding logins " + JSON.stringify(testCase.savedLogins));
await _addSavedLogins(testCase.savedLogins);
for (let login of testCase.savedLogins) {
info("Adding login " + JSON.stringify(login));
_addSavedLogin(login.username);
}
}
info("Opening tab");

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

@ -166,7 +166,7 @@ add_task(async function test_doorhanger_dismissal_on_change() {
"form-basic-username",
"form-basic-password"
);
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
let passwordFilledPromise = listenForTestNotification(
"PasswordEditedOrGenerated"

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

@ -30,7 +30,7 @@ add_task(async function test_httpsUpgradeCaptureFields_noChange() {
info(
"Check that we don't prompt to remember when capturing an upgraded login with no change"
);
await Services.logins.addLoginAsync(login1);
Services.logins.addLogin(login1);
// Sanity check the HTTP login exists.
let logins = Services.logins.getAllLogins();
Assert.equal(logins.length, 1, "Should have the HTTP login");
@ -73,7 +73,7 @@ add_task(async function test_httpsUpgradeCaptureFields_changePW() {
info(
"Check that we prompt to change when capturing an upgraded login with a new PW"
);
await Services.logins.addLoginAsync(login1);
Services.logins.addLogin(login1);
// Sanity check the HTTP login exists.
let logins = Services.logins.getAllLogins();
Assert.equal(logins.length, 1, "Should have the HTTP login");
@ -131,7 +131,8 @@ add_task(
info(
"Check that we prompt to change and properly save when capturing an upgraded login with a new PW when an http login also exists for that username"
);
await Services.logins.addLogins([login1, login1HTTPS]);
Services.logins.addLogin(login1);
Services.logins.addLogin(login1HTTPS);
let logins = Services.logins.getAllLogins();
Assert.equal(logins.length, 2, "Should have both HTTP and HTTPS logins");
@ -212,7 +213,7 @@ add_task(
add_task(async function test_httpsUpgradeCaptureFields_captureMatchingHTTP() {
info("Capture a new HTTP login which matches a stored HTTPS one.");
await Services.logins.addLoginAsync(login1HTTPS);
Services.logins.addLogin(login1HTTPS);
await testSubmittingLoginFormHTTP(
"subtst_notifications_1.html",

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

@ -96,7 +96,7 @@ async function test_save_change(testData) {
} = testData;
// Add a login for the origin of the form if testing a change notification.
if (oldPassword) {
await Services.logins.addLoginAsync(
Services.logins.addLogin(
LoginTestUtils.testData.formLogin({
origin: "https://example.com",
formActionOrigin: "https://example.com",

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

@ -71,7 +71,7 @@ add_task(async function test_edit_password() {
// Create the pre-existing logins when needed.
if (testCase.usernameInPageExists) {
await Services.logins.addLoginAsync(
Services.logins.addLogin(
LoginTestUtils.testData.formLogin({
origin: "https://example.com",
formActionOrigin: "https://example.com",
@ -82,7 +82,7 @@ add_task(async function test_edit_password() {
}
if (testCase.usernameChangedToExists) {
await Services.logins.addLoginAsync(
Services.logins.addLogin(
LoginTestUtils.testData.formLogin({
origin: "https://example.com",
formActionOrigin: "https://example.com",

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

@ -419,7 +419,7 @@ add_task(async function test_noPasswordField() {
add_task(async function test_pwOnlyNewLoginMatchesUPForm() {
info("Check for update popup when new existing pw-only login matches form.");
await Services.logins.addLoginAsync(login2);
Services.logins.addLogin(login2);
await testSubmittingLoginFormHTTP(
"subtst_notifications_1.html",
async function(fieldValues) {
@ -473,7 +473,7 @@ add_task(async function test_pwOnlyNewLoginMatchesUPForm() {
add_task(async function test_pwOnlyOldLoginMatchesUPForm() {
info("Check for update popup when old existing pw-only login matches form.");
await Services.logins.addLoginAsync(login2);
Services.logins.addLogin(login2);
// Change the timePasswordChanged to be old so that the password won't be
// revealed in the doorhanger.
@ -542,7 +542,7 @@ add_task(async function test_pwOnlyFormMatchesLogin() {
info(
"Check for no notification popup when pw-only form matches existing login."
);
await Services.logins.addLoginAsync(login1);
Services.logins.addLogin(login1);
await testSubmittingLoginFormHTTP("subtst_notifications_6.html", function(
fieldValues
@ -571,7 +571,7 @@ add_task(async function test_pwOnlyFormDoesntMatchExisting() {
info(
"Check for notification popup when pw-only form doesn't match existing login."
);
await Services.logins.addLoginAsync(login1B);
Services.logins.addLogin(login1B);
await testSubmittingLoginFormHTTP(
"subtst_notifications_6.html",
@ -601,7 +601,7 @@ add_task(async function test_pwOnlyFormDoesntMatchExisting() {
add_task(async function test_changeUPLoginOnUPForm_dont() {
info("Check for change-password popup, u+p login on u+p form. (not changed)");
await Services.logins.addLoginAsync(login1);
Services.logins.addLogin(login1);
await testSubmittingLoginFormHTTP(
"subtst_notifications_8.html",
@ -642,7 +642,7 @@ add_task(async function test_changeUPLoginOnUPForm_dont() {
add_task(async function test_changeUPLoginOnUPForm_remove() {
info("Check for change-password popup, u+p login on u+p form. (remove)");
await Services.logins.addLoginAsync(login1);
Services.logins.addLogin(login1);
await testSubmittingLoginFormHTTP(
"subtst_notifications_8.html",
@ -683,7 +683,7 @@ add_task(async function test_changeUPLoginOnUPForm_remove() {
add_task(async function test_changeUPLoginOnUPForm_change() {
info("Check for change-password popup, u+p login on u+p form.");
await Services.logins.addLoginAsync(login1);
Services.logins.addLogin(login1);
await testSubmittingLoginFormHTTP(
"subtst_notifications_8.html",
@ -739,7 +739,7 @@ add_task(async function test_changeUPLoginOnUPForm_change() {
add_task(async function test_changePLoginOnUPForm() {
info("Check for change-password popup, p-only login on u+p form (empty u).");
await Services.logins.addLoginAsync(login2);
Services.logins.addLogin(login2);
await testSubmittingLoginFormHTTP(
"subtst_notifications_9.html",
@ -927,7 +927,7 @@ add_task(async function test_change2pw0unExistingDifferentUP() {
"is submitted and there is a saved login with a username and different password."
);
await Services.logins.addLoginAsync(login1B);
Services.logins.addLogin(login1B);
await testSubmittingLoginFormHTTP(
"subtst_notifications_2pw_0un.html",
@ -961,7 +961,7 @@ add_task(async function test_change2pw0unExistingDifferentP() {
"is submitted and there is a saved login with no username and different password."
);
await Services.logins.addLoginAsync(login2B);
Services.logins.addLogin(login2B);
await testSubmittingLoginFormHTTP(
"subtst_notifications_2pw_0un.html",
@ -995,7 +995,7 @@ add_task(async function test_change2pw0unExistingWithSameP() {
"is submitted and there is a saved login with a username and the same password."
);
await Services.logins.addLoginAsync(login2);
Services.logins.addLogin(login2);
await testSubmittingLoginFormHTTP(
"subtst_notifications_2pw_0un.html",
@ -1025,7 +1025,7 @@ add_task(async function test_change2pw0unExistingWithSameP() {
add_task(async function test_changeUPLoginOnPUpdateForm() {
info("Check for change-password popup, u+p login on password update form.");
await Services.logins.addLoginAsync(login1);
Services.logins.addLogin(login1);
await testSubmittingLoginFormHTTP(
"subtst_notifications_change_p.html",

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

@ -89,7 +89,7 @@ async function test_save_change(testData) {
} = testData;
// Add a login for the origin of the form if testing a change notification.
if (oldPassword) {
await Services.logins.addLoginAsync(
Services.logins.addLogin(
LoginTestUtils.testData.formLogin({
origin: "https://example.com",
formActionOrigin: "https://example.com",

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

@ -276,7 +276,7 @@ function _validateTestCase(tc) {
async function test_submit_telemetry(tc) {
if (tc.savedLogin) {
await Services.logins.addLoginAsync(
Services.logins.addLogin(
LoginTestUtils.testData.formLogin({
origin: "https://example.com",
formActionOrigin: "https://example.com",

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

@ -57,7 +57,7 @@ add_task(async function test_edit_username() {
// Create the pre-existing logins when needed.
if (testCase.usernameInPageExists) {
await Services.logins.addLoginAsync(
Services.logins.addLogin(
LoginTestUtils.testData.formLogin({
origin: "https://example.com",
formActionOrigin: "https://example.com",
@ -68,7 +68,7 @@ add_task(async function test_edit_username() {
}
if (testCase.usernameChangedToExists) {
await Services.logins.addLoginAsync(
Services.logins.addLogin(
LoginTestUtils.testData.formLogin({
origin: "https://example.com",
formActionOrigin: "https://example.com",

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

@ -5,7 +5,7 @@
"use strict";
add_setup(async () => {
add_setup(function() {
let nsLoginInfo = Components.Constructor(
"@mozilla.org/login-manager/loginInfo;1",
Ci.nsILoginInfo,
@ -30,7 +30,8 @@ add_setup(async () => {
"testpass2"
);
await Services.logins.addLogins([login1, login2]);
Services.logins.addLogin(login1);
Services.logins.addLogin(login2);
});
add_task(async function test_autocompleteFromUsername() {

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

@ -1,19 +1,21 @@
"use strict";
add_setup(async () => {
const login1 = LoginTestUtils.testData.formLogin({
add_setup(async function() {
let login = LoginTestUtils.testData.formLogin({
origin: "http://10.0.0.0",
formActionOrigin: "https://example.org",
username: "username1",
password: "password1",
});
const login2 = LoginTestUtils.testData.formLogin({
Services.logins.addLogin(login);
login = LoginTestUtils.testData.formLogin({
origin: "https://example.org",
formActionOrigin: "https://example.org",
username: "username2",
password: "password2",
});
await Services.logins.addLogins([login1, login2]);
Services.logins.addLogin(login);
});
add_task(async function test_warningForLocalIP() {

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

@ -328,7 +328,7 @@ add_task(async function test_normal_popup_notification_3() {
);
Services.logins.removeAllUserFacingLogins();
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
let allLogins = Services.logins.getAllLogins();
// Sanity check the HTTP login exists.
Assert.equal(allLogins.length, 1, "Should have the HTTP login");
@ -387,7 +387,7 @@ add_task(async function test_private_popup_notification_3b() {
);
Services.logins.removeAllUserFacingLogins();
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
let allLogins = Services.logins.getAllLogins();
// Sanity check the HTTP login exists.
Assert.equal(allLogins.length, 1, "Should have the HTTP login");
@ -447,7 +447,7 @@ add_task(async function test_normal_new_password_4() {
" add a new password: popup notification should appear"
);
Services.logins.removeAllUserFacingLogins();
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
let allLogins = Services.logins.getAllLogins();
// Sanity check the HTTP login exists.
Assert.equal(allLogins.length, 1, "Should have the HTTP login");
@ -620,7 +620,7 @@ add_task(async function test_normal_with_login_6() {
add_task(async function test_normal_autofilled_7() {
info("test 7: verify that the user/pass pair was autofilled");
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
// Sanity check the HTTP login exists.
Assert.equal(

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

@ -59,7 +59,8 @@ add_task(async function test_changeUPLoginOnPUpdateForm_accept() {
info(
"Select an u+p login from multiple logins, on password update form, and accept."
);
await Services.logins.addLogins([login1, login1B]);
Services.logins.addLogin(login1);
Services.logins.addLogin(login1B);
let selectDialogPromise = TestUtils.topicObserved("select-dialog-loaded");
@ -121,7 +122,8 @@ add_task(async function test_changeUPLoginOnPUpdateForm_cancel() {
info(
"Select an u+p login from multiple logins, on password update form, and cancel."
);
await Services.logins.addLogins([login1, login1B]);
Services.logins.addLogin(login1);
Services.logins.addLogin(login1B);
let selectDialogPromise = TestUtils.topicObserved("select-dialog-loaded");

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

@ -182,117 +182,6 @@ function getPasswordEditedMessage() {
});
}
/**
* Create a login form and insert into contents dom (identified by id
* `content`). If the form (identified by its number) is already present in the
* dom, it gets replaced.
*
* @param {number} [num = 1] - number of the form, used as id, eg `form1`
* @param {string} [action = ""] - action attribute of the form
* @param {string} [autocomplete = null] - forms autocomplete attribute. Default is none
* @param {object} [username = {}] - object describing attributes to the username field:
* @param {string} [username.id = null] - id of the field
* @param {string} [username.name = "uname"] - name attribute
* @param {string} [username.type = "text"] - type of the field
* @param {string} [username.value = null] - initial value of the field
* @param {string} [username.autocomplete = null] - autocomplete attribute
* @param {object} [password = {}] - an object describing attributes to the password field. If falsy, do not create a password field
* @param {string} [password.id = null] - id of the field
* @param {string} [password.name = "pword"] - name attribute
* @param {string} [password.type = "password"] - type of the field
* @param {string} [password.value = null] - initial value of the field
* @param {string} [password.label = null] - if present, wrap field in a label containing its value
* @param {string} [password.autocomplete = null] - autocomplete attribute
*
* @return {HTMLDomElement} the form
*/
function createLoginForm({
num = 1,
action = "",
autocomplete = null,
username = {},
password = {},
} = {}) {
username.id ||= null;
username.name ||= "uname";
username.type ||= "text";
username.value ||= null;
username.autocomplete ||= null;
password.id ||= null;
password.name ||= "pword";
password.type ||= "password";
password.value ||= null;
password.label ||= null;
password.autocomplete ||= null;
info(
`Creating login form ${JSON.stringify({ num, action, username, password })}`
);
const form = document.createElement("form");
form.id = `form${num}`;
form.action = action;
form.onsubmit = () => false;
if (autocomplete != null) {
form.setAttribute("autocomplete", autocomplete);
}
const usernameInput = document.createElement("input");
if (username.id != null) {
usernameInput.id = username.id;
}
usernameInput.type = username.type;
usernameInput.name = username.name;
if (username.value != null) {
usernameInput.value = username.value;
}
if (username.autocomplete != null) {
usernameInput.setAttribute("autocomplete", username.autocomplete);
}
form.appendChild(usernameInput);
if (password) {
const passwordInput = document.createElement("input");
if (password.id != null) {
passwordInput.id = password.id;
}
passwordInput.type = password.type;
passwordInput.name = password.name;
if (password.value != null) {
passwordInput.value = password.value;
}
if (password.autocomplete != null) {
passwordInput.setAttribute("autocomplete", password.autocomplete);
}
if (password.label != null) {
const passwordLabel = document.createElement("label");
passwordLabel.innerText = password.label;
passwordLabel.appendChild(passwordInput);
form.appendChild(passwordLabel);
} else {
form.appendChild(passwordInput);
}
}
const submitButton = document.createElement("button");
submitButton.type = "submit";
submitButton.name = "submit";
submitButton.innerText = "Submit";
form.appendChild(submitButton);
const content = document.getElementById("content");
const oldForm = document.getElementById(form.id);
if (oldForm) {
content.replaceChild(form, oldForm);
} else {
content.appendChild(form);
}
return form;
}
/**
* Check for expected username/password in form.
* @see `checkForm` below for a similar function.
@ -814,52 +703,31 @@ function runInParent(aFunctionOrURL) {
return chromeScript;
}
/** Manage logins in parent chrome process.
* */
function manageLoginsInParent() {
return runInParent(function addLoginsInParentInner() {
/** Initialize with a list of logins. The logins are added within the parent chrome process.
* @param {array} aLogins - a list of logins to add. Each login is an array of the arguments
* that would be passed to nsLoginInfo.init().
*/
function addLoginsInParent(...aLogins) {
let script = runInParent(function addLoginsInParentInner() {
/* eslint-env mozilla/chrome-script */
addMessageListener("removeAllUserFacingLogins", () => {
Services.logins.removeAllUserFacingLogins();
});
/* eslint-env mozilla/chrome-script */
addMessageListener("addLogins", async logins => {
addMessageListener("addLogins", logins => {
let nsLoginInfo = Components.Constructor(
"@mozilla.org/login-manager/loginInfo;1",
Ci.nsILoginInfo,
"init"
);
const loginInfos = logins.map(login => new nsLoginInfo(...login));
try {
await Services.logins.addLogins(loginInfos);
} catch (e) {
assert.ok(false, "addLogins threw: " + e);
for (let login of logins) {
let loginInfo = new nsLoginInfo(...login);
try {
Services.logins.addLogin(loginInfo);
} catch (e) {
assert.ok(false, "addLogin threw: " + e);
}
}
});
});
}
/** Initialize with a list of logins. The logins are added within the parent chrome process.
* @param {array} aLogins - a list of logins to add. Each login is an array of the arguments
* that would be passed to nsLoginInfo.init().
*/
async function addLoginsInParent(...aLogins) {
const script = manageLoginsInParent();
await script.sendQuery("addLogins", aLogins);
return script;
}
/** Initialize with a list of logins, after removing all user facing logins.
* The logins are added within the parent chrome process.
* @param {array} aLogins - a list of logins to add. Each login is an array of the arguments
* that would be passed to nsLoginInfo.init().
*/
async function setStoredLoginsAsync(...aLogins) {
const script = manageLoginsInParent();
script.sendQuery("removeAllUserFacingLogins");
await script.sendQuery("addLogins", aLogins);
script.sendQuery("addLogins", aLogins);
return script;
}

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

@ -40,7 +40,7 @@ if (LoginHelper.improvedPasswordRulesEnabled) {
* the test can start checking filled-in values. Tests that check observer
* notifications might be confused by this.
*/
async function commonInit(selfFilling, testDependsOnDeprecatedLogin) {
function commonInit(selfFilling, testDependsOnDeprecatedLogin) {
var pwmgr = Services.logins;
assert.ok(pwmgr != null, "Access LoginManager");
@ -69,7 +69,7 @@ async function commonInit(selfFilling, testDependsOnDeprecatedLogin) {
"uname",
"pword"
);
await pwmgr.addLoginAsync(login);
pwmgr.addLogin(login);
}
// Last sanity check
@ -145,11 +145,8 @@ addMessageListener("cleanup", () => {
addMessageListener(
"setupParent",
async ({
selfFilling = false,
testDependsOnDeprecatedLogin = false,
} = {}) => {
await commonInit(selfFilling, testDependsOnDeprecatedLogin);
({ selfFilling = false, testDependsOnDeprecatedLogin = false } = {}) => {
commonInit(selfFilling, testDependsOnDeprecatedLogin);
sendAsyncMessage("doneSetup");
}
);

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

@ -40,7 +40,7 @@ async function openDocumentInWindow(win) {
async function test_password_autofilled() {
info("Adding one login for the page");
await addLoginsInParent([DEFAULT_ORIGIN, DEFAULT_ORIGIN, null, "user", "omgsecret!"]);
addLoginsInParent([DEFAULT_ORIGIN, DEFAULT_ORIGIN, null, "user", "omgsecret!"]);
let numLogins = await LoginManager.countLogins(DEFAULT_ORIGIN, DEFAULT_ORIGIN, null);
is(numLogins, 1, "Correct number of logins");

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

@ -11,12 +11,12 @@
</head>
<body>
<script>
const origin = window.location.origin;
const readyPromise = registerRunTests(1)
.then(() => addLoginsInParent(
[origin, "https://autofill", null, "user1", "pass1"],
[origin, "https://autofill", null, "user2", "pass2"]
));
let readyPromise = registerRunTests(1);
let origin = window.location.origin;
addLoginsInParent(
[origin, "https://autofill", null, "user1", "pass1"],
[origin, "https://autofill", null, "user2", "pass2"]);
function preventDefaultAndStopProgagation(event) {
event.preventDefault();

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

@ -11,38 +11,8 @@
</head>
<body>
Login Manager test: no duplicate logins when using autofill and autocomplete with related realms
<p id="display"></p>
<div id="content"></div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Login Manager: related realms autofill/autocomplete. **/
function restoreForm(form) {
form.uname.value = "";
form.pword.value = "";
form.uname.focus();
}
function sendFakeAutocompleteEvent(element) {
const acEvent = document.createEvent("HTMLEvents");
acEvent.initEvent("DOMAutoComplete", true, false);
element.dispatchEvent(acEvent);
}
function spinEventLoop() {
return Promise.resolve();
}
async function promiseACPopupClosed() {
return SimpleTest.promiseWaitForCondition(async () => {
const popupState = await getPopupState();
return !popupState.open;
}, "Wait for AC popup to be closed");
}
add_setup(async () => {
await addLoginsInParent(
<script>
addLoginsInParent(
// Simple related domain relationship where example.com and other-example.com are in the related domains list
["https://other-example.com", "https://other-example.com", null, "relatedUser1", "relatedPass1", "uname", "pword"],
@ -55,35 +25,74 @@ add_setup(async () => {
// Ensures there are no duplicates for the exact domain that the user is on
["https://example.com", "https://example.com", null, "exactUser1", "exactPass1", "uname", "pword"],
["https://www.example.com", "https://www.example.com", null, "exactWWWUser1", "exactWWWPass1", "uname", "pword"],
);
);
</script>
<p id="display"></p>
<div id="content">
<form id="form1" action="https://www.example.com" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Login Manager: related realms autofill/autocomplete. **/
const uname = getFormElementByName(1, "uname");
const pword = getFormElementByName(1, "pword");
function restoreForm() {
uname.value = "";
pword.value = "";
uname.focus();
}
function sendFakeAutocompleteEvent(element) {
var acEvent = document.createEvent("HTMLEvents");
acEvent.initEvent("DOMAutoComplete", true, false);
element.dispatchEvent(acEvent);
}
function spinEventLoop() {
return Promise.resolve();
}
async function promiseACPopupClosed() {
return SimpleTest.promiseWaitForCondition(async () => {
let popupState = await getPopupState();
return !popupState.open;
}, "Wait for AC popup to be closed");
}
add_setup(async () => {
listenForUnexpectedPopupShown();
});
add_task(async function test_no_duplicates_autocomplete_autofill() {
const form = createLoginForm({
action: "https://www.example.com"
});
await promiseFormsProcessedInSameProcess();
await SimpleTest.promiseFocus(window);
const results = await popupBy(() => {
checkLoginForm(form.uname, "exactUser1", form.pword, "exactPass1")
restoreForm(form);
let results = await popupBy(() => {
checkLoginForm(uname, "exactUser1", pword, "exactPass1")
restoreForm();
});
const popupState = await getPopupState();
let popupState = await getPopupState();
is(popupState.selectedIndex, -1, "Check no entires are selected upon opening");
const expectedMenuItems = ["exactUser1", "exactWWWUser1", "relatedUser1", "subUser1"];
let expectedMenuItems = ["exactUser1", "exactWWWUser1", "relatedUser1", "subUser1"];
checkAutoCompleteResults(results, expectedMenuItems, window.location.host, "Check all menuitems are displayed correctly");
const acEvents = await getTelemetryEvents({ process: "parent", filterProps: TelemetryFilterPropsAC, clear: true });
let acEvents = await getTelemetryEvents({ process: "parent", filterProps: TelemetryFilterPropsAC, clear: true });
is(acEvents.length, 1, "One autocomplete event");
checkACTelemetryEvent(acEvents[0], form.uname, {
checkACTelemetryEvent(acEvents[0], uname, {
"hadPrevious": "0",
"login": expectedMenuItems.length + "",
"loginsFooter": "1"
});
restoreForm(form);
restoreForm();
synthesizeKey("KEY_Escape");
});
</script>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -13,30 +13,52 @@
Login Manager test: logins with non-matching formActionOrigin appear in autocomplete dropdown
<script>
const chromeScript = runChecksAfterCommonInit();
var chromeScript = runChecksAfterCommonInit();
addLoginsInParent([window.location.origin, "https://differentFormSubmitURL", null,
"dfsu1", "dfsp1", "uname", "pword"]);
</script>
<p id="display"></p>
<!-- we presumably can't hide the content for this test. -->
<div id="content"></div>
<div id="content">
<!-- form1 tests multiple matching logins -->
<form id="form1" action="https://autocomplete:8888/formtest.js" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Login Manager: multiple login autocomplete. **/
const uname = getFormElementByName(1, "uname");
const pword = getFormElementByName(1, "pword");
// Restore the form to the default state.
function restoreForm() {
uname.value = "";
pword.value = "";
uname.focus();
}
function spinEventLoop() {
return Promise.resolve();
}
add_setup(async () => {
await addLoginsInParent(
[window.location.origin, "https://differentFormSubmitURL", null, "dfsu1", "dfsp1", "uname", "pword"]
);
listenForUnexpectedPopupShown();
});
add_task(async function test_form1_initial_empty() {
const form = createLoginForm();
await SimpleTest.promiseFocus(window);
// Make sure initial form is empty.
checkLoginForm(form.uname, "", form.pword, "");
const popupState = await getPopupState();
checkLoginForm(uname, "", pword, "");
let popupState = await getPopupState();
is(popupState.open, false, "Check popup is initially closed");
});
@ -45,29 +67,23 @@ add_task(async function test_form1_initial_empty() {
* in the autocomplete popup.
*/
add_task(async function test_form1_menu_shows_logins_for_different_formActionOrigin() {
const form = createLoginForm();
await SimpleTest.promiseFocus(window);
// Trigger autocomplete popup
form.uname.value = "";
form.pword.value = "";
form.uname.focus();
restoreForm();
const autocompleteItems = await popupByArrowDown();
const popupState = await getPopupState();
let popupState = await getPopupState();
is(popupState.selectedIndex, -1, "Check no entries are selected upon opening");
const expectedMenuItems = ["dfsu1"];
let expectedMenuItems = ["dfsu1"];
checkAutoCompleteResults(autocompleteItems, expectedMenuItems, window.location.host, "Check all menuitems are displayed correctly.");
synthesizeKey("KEY_ArrowDown"); // first item
checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update just by selecting
checkLoginForm(uname, "", pword, ""); // value shouldn't update just by selecting
synthesizeKey("KEY_Enter");
await promiseFormsProcessedInSameProcess();
checkLoginForm(form.uname, "dfsu1", form.pword, "dfsp1");
checkLoginForm(uname, "dfsu1", pword, "dfsp1");
});
</script>
</pre>

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

@ -12,9 +12,9 @@
<body>
<script>
const chromeScript = runChecksAfterCommonInit();
var chromeScript = runChecksAfterCommonInit();
const setupScript = runInParent(async function setup() {
var setupScript = runInParent(function setup() {
// Create some logins just for this form, since we'll be deleting them.
var nsLoginInfo = Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
Ci.nsILoginInfo, "init");
@ -62,21 +62,23 @@ const setupScript = runInParent(async function setup() {
// try/catch in case someone runs the tests manually, twice.
await Services.logins.addLogins([
logins.login0,
logins.login1,
logins.login2,
logins.login3,
logins.login4,
]);
try {
Services.logins.addLogin(logins.login0);
Services.logins.addLogin(logins.login1);
Services.logins.addLogin(logins.login2);
Services.logins.addLogin(logins.login3);
Services.logins.addLogin(logins.login4);
} catch (e) {
assert.ok(false, "addLogin threw: " + e);
}
addMessageListener("addLogin", loginVariableName => {
const login = logins[loginVariableName];
let login = logins[loginVariableName];
assert.ok(!!login, "Login to add is defined: " + loginVariableName);
Services.logins.addLogin(login);
});
addMessageListener("removeLogin", loginVariableName => {
const login = logins[loginVariableName];
let login = logins[loginVariableName];
assert.ok(!!login, "Login to delete is defined: " + loginVariableName);
Services.logins.removeLogin(login);
});

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

@ -11,27 +11,9 @@
</head>
<body>
Login Manager test: related realms autocomplete
<p id="display"></p>
<div id="content"></div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Login Manager: related realms autocomplete. **/
function sendFakeAutocompleteEvent(element) {
var acEvent = document.createEvent("HTMLEvents");
acEvent.initEvent("DOMAutoComplete", true, false);
element.dispatchEvent(acEvent);
}
async function promiseACPopupClosed() {
return SimpleTest.promiseWaitForCondition(async () => {
const popupState = await getPopupState();
return !popupState.open;
}, "Wait for AC popup to be closed");
}
add_setup(async () => {
await addLoginsInParent(
<script>
addLoginsInParent(
// Simple related domain relationship where example.com and other-example.com are in the related domains list
["https://other-example.com", "https://other-example.com", null, "relatedUser1", "relatedPass1", "uname", "pword"],
@ -40,64 +22,105 @@ add_setup(async () => {
// where the sign in page is actually signin.ebay.com/signin.ebay.co.uk but credentials could have manually been entered
// for ebay.com/ebay.co.uk or automatically stored as signin.ebay.com/sigin.ebay.co.uk
["https://sub.example.co.uk", "https://sub.example.co.uk", null, "subUser1", "subPass1", "uname", "pword"],
);
);
</script>
<p id="display"></p>
<div id="content">
<form id="form1" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Login Manager: related realms autocomplete. **/
const uname = getFormElementByName(1, "uname");
const pword = getFormElementByName(1, "pword");
function restoreForm() {
uname.value = "";
pword.value = "";
uname.focus();
}
function sendFakeAutocompleteEvent(element) {
var acEvent = document.createEvent("HTMLEvents");
acEvent.initEvent("DOMAutoComplete", true, false);
element.dispatchEvent(acEvent);
}
function spinEventLoop() {
return Promise.resolve();
}
async function promiseACPopupClosed() {
return SimpleTest.promiseWaitForCondition(async () => {
let popupState = await getPopupState();
return !popupState.open;
}, "Wait for AC popup to be closed");
}
add_setup(async () => {
listenForUnexpectedPopupShown();
});
add_task(async function test_form1_initial_empty() {
const form = createLoginForm();
await SimpleTest.promiseFocus(window);
// Make sure initial form is empty.
checkLoginForm(form.uname, "", form.pword, "");
const popupState = await getPopupState();
checkLoginForm(uname, "", pword, "");
let popupState = await getPopupState();
is(popupState.open, false, "Check popup is initially closed");
});
add_task(async function test_form_related_domain_menuitems() {
const form = createLoginForm();
form.uname.focus();
await SimpleTest.promiseFocus(window);
restoreForm();
const autocompleteItems = await popupByArrowDown();
const popupState = await getPopupState();
let popupState = await getPopupState();
is(popupState.selectedIndex, -1, "Check no entires are selected upon opening");
const expectedMenuItems = ["relatedUser1", "subUser1"];
let expectedMenuItems = ["relatedUser1", "subUser1"];
checkAutoCompleteResults(autocompleteItems, expectedMenuItems, window.location.host, "Check all menuitems are displayed correctly");
const acEvents = await getTelemetryEvents({ process: "parent", filterProps: TelemetryFilterPropsAC, clear: true });
let acEvents = await getTelemetryEvents({ process: "parent", filterProps: TelemetryFilterPropsAC, clear: true });
is(acEvents.length, 1, "One autocomplete event");
checkACTelemetryEvent(acEvents[0], form.uname, {
checkACTelemetryEvent(acEvents[0], uname, {
"hadPrevious": "0",
"login": expectedMenuItems.length + "",
"loginsFooter": "1"
});
checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update just by opening
checkLoginForm(uname, "", pword, ""); // value shouldn't update just by opening
synthesizeKey("KEY_ArrowDown"); // first item
checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update just by selecting
checkLoginForm(uname, "", pword, ""); // value shouldn't update just by selecting
synthesizeKey("KEY_Enter");
await promiseFormsProcessedInSameProcess();
is(form.pword.value, "relatedPass1", "password should match the login that was selected");
checkLoginForm(form.uname, "relatedUser1", form.pword, "relatedPass1");
is(pword.value, "relatedPass1", "password should match the login that was selected");
checkLoginForm(uname, "relatedUser1", pword, "relatedPass1");
form.uname.value = "";
form.pword.value = "";
form.uname.focus();
restoreForm();
await popupByArrowDown();
synthesizeKey("KEY_ArrowDown"); // first item
synthesizeKey("KEY_ArrowDown"); // second item
checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update just by selecting
checkLoginForm(uname, "", pword, ""); // value shouldn't update just by selecting
synthesizeKey("KEY_Enter");
await promiseFormsProcessedInSameProcess();
is(form.pword.value, "subPass1", "password should match the login that was selected");
checkLoginForm(form.uname, "subUser1", form.pword, "subPass1");
is(pword.value, "subPass1", "password should match the login that was selected");
checkLoginForm(uname, "subUser1", pword, "subPass1");
restoreForm();
});
</script>
</pre>
</body>

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

@ -11,40 +11,64 @@
</head>
<body>
Login Manager test: logins with non-exact match origin appear in autocomplete dropdown
<p id="display"></p>
<!-- we presumably can't hide the content for this test. -->
<div id="content"></div>
<pre id="test">
<script class="testbody" type="text/javascript">
const setupScript = runInParent(function setup() {
<script>
let origin = window.location.origin;
let lastDot = origin.lastIndexOf(".");
let suffix = origin.slice(lastDot);
let baseHost = "http://example" + suffix;
let baseSecureHost = "https://example" + suffix;
let oldHost = "http://old.example" + suffix;
let oldSecureHost = "https://old.example" + suffix;
let newHost = "https://new.example" + suffix;
addLoginsInParent(
// The first two logins should never be visible on https: versions of
// *.example.com since the login is for http: and an https: login exists for this username.
[oldHost, oldSecureHost, null, "dsdu1", "dsdp1new", "uname", "pword"],
[baseHost, baseSecureHost, null, "dsdu1", "dsdp1", "uname", "pword"],
[oldSecureHost, oldSecureHost, null, "dsdu1", "dsdp1", "uname", "pword"],
[baseSecureHost, baseSecureHost, null, "dsdu1", "dsdp1", "uname", "pword"],
[newHost, newHost, null, "dsdu1", "dsdp1prime", "uname", "pword"]);
var setupScript = runInParent(function setup() {
addMessageListener("getDateString", () => {
const dateAndTimeFormatter = new Services.intl.DateTimeFormat(undefined, { dateStyle: "medium" });
let dateAndTimeFormatter = new Services.intl.DateTimeFormat(undefined, { dateStyle: "medium" });
return dateAndTimeFormatter.format(new Date());
});
});
</script>
<p id="display"></p>
<!-- we presumably can't hide the content for this test. -->
<div id="content">
<!-- form1 tests multiple matching logins -->
<form id="form1" action="https://otherexample.com/formtest.js" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
const uname = getFormElementByName(1, "uname");
const pword = getFormElementByName(1, "pword");
// Restore the form to the default state.
function restoreForm() {
uname.value = "";
pword.value = "";
uname.focus();
}
function spinEventLoop() {
return Promise.resolve();
}
add_setup(async () => {
const origin = window.location.origin;
const lastDot = origin.lastIndexOf(".");
const suffix = origin.slice(lastDot);
const baseHost = "http://example" + suffix;
const baseSecureHost = "https://example" + suffix;
const oldHost = "http://old.example" + suffix;
const oldSecureHost = "https://old.example" + suffix;
const newHost = "https://new.example" + suffix;
await addLoginsInParent(
// The first two logins should never be visible on https: versions of
// *.example.com since the login is for http: and an https: login exists for this username.
[oldHost, oldSecureHost, null, "dsdu1", "dsdp1new", "uname", "pword"],
[baseHost, baseSecureHost, null, "dsdu1", "dsdp1", "uname", "pword"],
[oldSecureHost, oldSecureHost, null, "dsdu1", "dsdp1", "uname", "pword"],
[baseSecureHost, baseSecureHost, null, "dsdu1", "dsdp1", "uname", "pword"],
[newHost, newHost, null, "dsdu1", "dsdp1prime", "uname", "pword"]
);
await SpecialPowers.pushPrefEnv({
set: [
["signon.includeOtherSubdomainsInLookup", true],
@ -54,13 +78,11 @@ add_setup(async () => {
});
add_task(async function test_form1_initial_empty() {
const form = createLoginForm({
action: "https://otherexample.com/formtest.js"
});
await SimpleTest.promiseFocus(window);
// Make sure initial form is empty.
checkLoginForm(form.uname, "", form.pword, "");
const popupState = await getPopupState();
checkLoginForm(uname, "", pword, "");
let popupState = await getPopupState();
is(popupState.open, false, "Check popup is initially closed");
});
@ -69,47 +91,41 @@ add_task(async function test_form1_initial_empty() {
* should appear in the autocomplete popup.
*/
add_task(async function test_form1_menu_shows_two_logins_same_usernames_for_different_subdomain() {
const form = createLoginForm({
action: "https://otherexample.com/formtest.js"
});
await SimpleTest.promiseFocus(window);
// Trigger autocomplete popup
form.uname.focus();
restoreForm();
const autocompleteItems = await popupByArrowDown();
const popupState = await getPopupState();
let popupState = await getPopupState();
is(popupState.selectedIndex, -1, "Check no entries are selected upon opening");
// The logins are added "today" and since they are duplicates, the date that they were last
// changed will be appended.
const dateString = await setupScript.sendQuery("getDateString");
const username = `dsdu1 (${dateString})`;
let dateString = await setupScript.sendQuery("getDateString");
let username = `dsdu1 (${dateString})`;
checkAutoCompleteResults(autocompleteItems, [username, username], window.location.host, "Check all menuitems are displayed correctly.");
synthesizeKey("KEY_ArrowDown"); // first item
checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update just by selecting
checkLoginForm(uname, "", pword, ""); // value shouldn't update just by selecting
synthesizeKey("KEY_Enter");
await promiseFormsProcessedInSameProcess();
is(form.pword.value, "dsdp1", "password should match the login that was selected");
checkLoginForm(form.uname, "dsdu1", form.pword, "dsdp1");
is(pword.value, "dsdp1", "password should match the login that was selected");
checkLoginForm(uname, "dsdu1", pword, "dsdp1");
form.uname.value = "";
form.pword.value = "";
form.uname.focus();
restoreForm();
await popupByArrowDown();
synthesizeKey("KEY_ArrowDown"); // first item
synthesizeKey("KEY_ArrowDown"); // second item
checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update just by selecting
checkLoginForm(uname, "", pword, ""); // value shouldn't update just by selecting
synthesizeKey("KEY_Enter");
await promiseFormsProcessedInSameProcess();
is(form.pword.value, "dsdp1prime", "Password should match the login that was selected");
checkLoginForm(form.uname, "dsdu1", form.pword, "dsdp1prime");
is(pword.value, "dsdp1prime", "Password should match the login that was selected");
checkLoginForm(uname, "dsdu1", pword, "dsdp1prime");
});
</script>
</pre>

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

@ -11,18 +11,36 @@
</head>
<body>
Login Manager test: Test that passwords are autocompleted into fields that were previously type=password
<script>
let origin = window.location.origin;
addLoginsInParent(
[origin, origin, null, "user1", "pass1"],
[origin, origin, null, "user2", "pass2"]);
</script>
<p id="display"></p>
<!-- we presumably can't hide the content for this test. -->
<div id="content"></div>
<div id="content">
<!-- form1 tests multiple matching logins -->
<form id="form1" action="https://example.com/formtest.js" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
const uname = getFormElementByName(1, "uname");
const pword = getFormElementByName(1, "pword");
// Restore the form to the default state.
function restoreForm(form) {
form.uname.value = "";
form.pword.value = "";
form.uname.focus();
function restoreForm() {
uname.value = "";
pword.value = "";
uname.focus();
}
function spinEventLoop() {
@ -30,70 +48,57 @@ function spinEventLoop() {
}
add_setup(async () => {
const origin = window.location.origin;
await addLoginsInParent(
[origin, origin, null, "user1", "pass1"],
[origin, origin, null, "user2", "pass2"]
);
listenForUnexpectedPopupShown();
});
add_task(async function test_form1_initial_empty() {
const form = createLoginForm({
action: "https://www.example.com/formtest.js"
});
await SimpleTest.promiseFocus(window);
// Make sure initial form is empty.
checkLoginForm(form.uname, "", form.pword, "");
const popupState = await getPopupState();
checkLoginForm(uname, "", pword, "");
let popupState = await getPopupState();
is(popupState.open, false, "Check popup is initially closed");
});
add_task(async function test_form1_password_to_type_text() {
const form = createLoginForm({
action: "https://www.example.com/formtest.js"
});
await SimpleTest.promiseFocus(window);
info("Setting the password field type to text");
// This is similar to a site implementing their own password visibility/unmasking toggle
form.pword.type = "text";
pword.type = "text";
// Trigger autocomplete popup
restoreForm(form);
restoreForm();
const autocompleteItems = await popupByArrowDown();
const popupState = await getPopupState();
let popupState = await getPopupState();
is(popupState.selectedIndex, -1, "Check no entries are selected upon opening");
checkAutoCompleteResults(autocompleteItems, ["user1", "user2"], window.location.host,
"Check all menuitems are displayed correctly.");
synthesizeKey("KEY_ArrowDown"); // first item
checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update just by selecting
checkLoginForm(uname, "", pword, ""); // value shouldn't update just by selecting
synthesizeKey("KEY_Enter");
await promiseFormsProcessedInSameProcess();
is(form.uname.value, "user1", "username should match the login, not the password");
is(form.pword.value, "pass1", "password should match the login, not the username");
checkLoginForm(form.uname, "user1", form.pword, "pass1");
is(uname.value, "user1", "username should match the login, not the password");
is(pword.value, "pass1", "password should match the login, not the username");
checkLoginForm(uname, "user1", pword, "pass1");
restoreForm(form);
restoreForm();
info("Focusing the password field");
form.pword.focus();
pword.focus();
await popupByArrowDown();
synthesizeKey("KEY_ArrowDown"); // first item
checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update just by selecting
checkLoginForm(uname, "", pword, ""); // value shouldn't update just by selecting
synthesizeKey("KEY_Enter");
await spinEventLoop();
is(form.pword.value, "pass1", "Password should match the login that was selected");
checkLoginForm(form.uname, "", form.pword, "pass1");
is(pword.value, "pass1", "Password should match the login that was selected");
checkLoginForm(uname, "", pword, "pass1");
});
</script>
</pre>

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

@ -9,64 +9,75 @@
<script type="text/javascript" src="pwmgr_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<script>
let readyPromise = registerRunTests(1);
let origin = window.location.origin;
addLoginsInParent(
[origin, "https://autocomplete", null, "user1", "pass1", "", ""],
[origin, "https://autocomplete", null, "user2", "pass2", "", ""]);
</script>
<body>
<p id="display"></p>
<div id="content"></div>
<div id="content">
<form id="form1" action="https://autocomplete" onsubmit="return false;">
<input type="text" id="uname">
<input type="password" id="pword">
<button type="submit">Submit</button>
</form>
<pre id="test">
<script>
const { ContentTaskUtils } = SpecialPowers.ChromeUtils.import(
let { ContentTaskUtils } = SpecialPowers.ChromeUtils.import(
"resource://testing-common/ContentTaskUtils.jsm"
);
add_setup(async () => {
const origin = window.location.origin;
await addLoginsInParent(
[origin, "https://autocomplete", null, "user1", "pass1", "", ""],
[origin, "https://autocomplete", null, "user2", "pass2", "", ""]
);
ok(readyPromise, "check promise is available");
await readyPromise;
});
add_task(async function test_field_highlight_on_autocomplete() {
const form = createLoginForm({
action: "https://autocomplete"
});
// Test username autocomplete.
let username = document.getElementById("uname");
let password = document.getElementById("pword");
await openPopupOn(form.uname);
await openPopupOn(username);
synthesizeKey("KEY_ArrowDown");
await synthesizeKey("KEY_Enter");
await ContentTaskUtils.waitForCondition(() => {
return form.uname.matches(":autofill")
return username.matches(":autofill")
}, "Highlight was successfully applied to the username field on username autocomplete");
ok(form.pword.matches(":autofill"),
ok(password.matches(":autofill"),
"Highlight was successfully applied to the password field on username autocomplete");
// Clear existing highlight on login fields. We check by pressing the tab key after backspace
// (by shifting focus to the next element) because the tab key was known to cause a bug where the
// highlight is applied once again. See Bug 1526522.
form.uname.focus();
username.focus();
synthesizeKey("KEY_Backspace");
synthesizeKey("KEY_Tab");
ok(!form.uname.matches(":autofill"),
ok(!username.matches(":autofill"),
"Highlight was successfully removed on the username field");
synthesizeKey("KEY_Backspace");
synthesizeKey("KEY_Tab");
ok(!form.pword.matches(":autofill"),
ok(!password.matches(":autofill"),
"Highlight was successfully removed on the password field");
// Clear login fields.
form.uname.value = "";
form.pword.value = "";
username.value = "";
password.value = "";
// Test password field autocomplete.
await openPopupOn(form.pword);
await openPopupOn(password);
synthesizeKey("KEY_ArrowDown");
synthesizeKey("KEY_Enter");
await ContentTaskUtils.waitForCondition(() => {
return form.pword.matches(":autofill");
return password.matches(":autofill");
}, "Highlight was successfully applied to the password field on password autocomplete");
// Clear existing highlight on the password field. We check by pressing the tab key after backspace
@ -75,12 +86,12 @@ add_task(async function test_field_highlight_on_autocomplete() {
synthesizeKey("KEY_Backspace");
synthesizeKey("KEY_Tab");
ok(!form.pword.matches(":autofill"),
ok(!password.matches(":autofill"),
"Highlight was successfully removed on the password field");
// Clear login fields.
form.uname.value = "";
form.pword.value = "";
username.value = "";
password.value = "";
});
</script>
</body>

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

@ -9,48 +9,58 @@
<script type="text/javascript" src="pwmgr_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<script>
let readyPromise = registerRunTests(1);
let origin = window.location.origin;
addLoginsInParent(
[origin, "https://autocomplete", null, "user1", "pass1", "", ""],
[origin, "https://autocomplete", null, "user2", "pass2", "", ""]);
</script>
<body>
<p id="display"></p>
<div id="content"></div>
<div id="content">
<form id="form" action="https://autocomplete" onsubmit="return false;">
<input type="text" id="uname" autocomplete="username">
<button type="submit">Submit</button>
</form>
<pre id="test">
<script>
const { ContentTaskUtils } = SpecialPowers.ChromeUtils.import(
let { ContentTaskUtils } = SpecialPowers.ChromeUtils.import(
"resource://testing-common/ContentTaskUtils.jsm"
);
add_setup(async () => {
await addLoginsInParent(
[location.origin, "https://autocomplete", null, "user1", "pass1", "", ""],
[location.origin, "https://autocomplete", null, "user2", "pass2", "", ""]
);
ok(readyPromise, "check promise is available");
await readyPromise;
});
add_task(async function test_username_field_in_username_only_form_highlight_on_autocomplete() {
const form = createLoginForm({
action: "https://autocomplete",
username: {
autocomplete: "username"
},
password: false
});
// Test username autocomplete.
const username = document.getElementById("uname");
await openPopupOn(form.uname);
await openPopupOn(username);
synthesizeKey("KEY_ArrowDown");
await synthesizeKey("KEY_Enter");
await ContentTaskUtils.waitForCondition(() => {
return form.uname.matches(":autofill");
return username.matches(":autofill");
}, "Highlight was successfully applied to the username field on username autocomplete");
// Clear existing highlight on login fields. We check by pressing the tab key after backspace
// (by shifting focus to the next element) because the tab key was known to cause a bug where the
// highlight is applied once again. See Bug 1526522.
form.uname.focus();
username.focus();
synthesizeKey("KEY_Backspace");
synthesizeKey("KEY_Tab");
ok(!form.uname.matches(":autofill"),
ok(!username.matches(":autofill"),
"Highlight was successfully removed on the username field");
// Clear login fields.
username.value = "";
});
</script>
</body>
</html>

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

@ -13,10 +13,54 @@
<body>
Login Manager test: autofill with autocomplete=new-password fields
<script>
function initLogins() {
Services.logins.removeAllUserFacingLogins();
const {LoginManagerParent} = ChromeUtils.import("resource://gre/modules/LoginManagerParent.jsm");
if (LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin()) {
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear();
}
}
runInParent(initLogins);
let origin = window.location.origin;
addLoginsInParent([origin, "https://autofill", null, "user1", "pass1"]);
let readyPromise = registerRunTests(3);
</script>
<p id="display"></p>
<!-- we presumably can't hide the content for this test. -->
<div id="content"></div>
<div id="content">
<!-- form1 is the reference, sanity-check -->
<form id="form1" action="https://autofill" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="p">
<button type="submit">Submit</button>
</form>
<!-- form2 uses a new-password type=password field -->
<form id="form2" action="https://autofill" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="password" autocomplete="new-password">
<button type="submit">Submit</button>
</form>
<!-- form3 has enough signal to make new-password heuristics (Bug 1595244) detect
a new password field, even though there is no autocomplete="new-password"
attribute on the <input type="password"> element-->
<form id="form3" action="https://autofill" onsubmit="return false;">
<input type="text" name="username">
<label>
New password
<input type="password" name="password">
</label>
<button type="submit">Submit</button>
</form>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
@ -90,14 +134,13 @@ async function checkTelemetryEventsPWGenUsed(expectedPWGenTelemetryEvents) {
ok(!telemetryEvents, `Expected to timeout waiting for there to be ${expectedPWGenTelemetryEvents + 1} events`);
}
function clearGeneratedPasswords() {
const { LoginManagerParent } = ChromeUtils.import("resource://gre/modules/LoginManagerParent.jsm");
if (LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin()) {
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear();
}
}
add_setup(async () => {
await SpecialPowers.pushPrefEnv({"set": [
["signon.generation.available", false],
["signon.generation.enabled", false],
]});
ok(readyPromise, "check promise is available");
await readyPromise;
let useEvents = await getTelemetryEvents({ process: "parent", filterProps: TelemetryFilterPropsUsed, clear: true });
is(useEvents.length, 0, "Expect 0 use events");
let showEvents = await getTelemetryEvents({ process: "parent", filterProps: TelemetryFilterPropsShown, clear: true });
@ -105,49 +148,24 @@ add_setup(async () => {
let acEvents = await getTelemetryEvents({ process: "parent", filterProps: TelemetryFilterPropsAC, clear: true });
is(acEvents.length, 0, "Expect 0 autocomplete events");
await SpecialPowers.pushPrefEnv({"set": [
["signon.generation.available", true],
["signon.generation.enabled", true],
]});
// This can be removed once Bug 1623431 is resolved.
document.getElementById("form3").reset();
});
add_task(async function test_autofillAutocompleteUsername_noGeneration() {
await SpecialPowers.pushPrefEnv({"set": [
["signon.generation.available", false],
["signon.generation.enabled", false],
]});
await setStoredLoginsAsync([location.origin, "https://autofill", null, "user1", "pass1"]);
createLoginForm({
num: 1,
action: "https://autofill",
password: {
name: "p"
}
});
const form2 = createLoginForm({
num: 2,
action: "https://autofill",
password: {
name: "password",
autocomplete: "new-password"
}
});
await promiseFormsProcessedInSameProcess(2);
// reference form was filled as expected?
checkForm(1, "user1", "pass1");
// 2nd form should not be filled
checkForm(2, "", "");
form2.uname.focus();
getFormElementByName(2, "uname").focus();
await showACPopup(2, ["user1"]);
let acEvents = await waitForTelemetryEventsCondition(events => {
return events.length == 1;
}, { process: "parent", filterProps: TelemetryFilterPropsAC, clear: true }, `Wait for there to be 1 autocomplete telemetry event`);
checkACTelemetryEvent(acEvents[0], form2.uname, {
checkACTelemetryEvent(acEvents[0], getFormElementByName(2, "uname"), {
"hadPrevious": "0",
"login": "1",
"loginsFooter": "1"
@ -155,39 +173,23 @@ add_task(async function test_autofillAutocompleteUsername_noGeneration() {
synthesizeKey("KEY_ArrowDown");
synthesizeKey("KEY_Enter");
await promiseFormsProcessedInSameProcess();
checkForm(2, "user1", "pass1");
await SpecialPowers.popPrefEnv();
recreateTree(document.getElementById("form2"));
});
add_task(async function test_autofillAutocompletePassword_noGeneration() {
await SpecialPowers.pushPrefEnv({"set": [
["signon.generation.available", false],
["signon.generation.enabled", false],
]});
await setStoredLoginsAsync([location.origin, "https://autofill", null, "user1", "pass1"]);
const form = createLoginForm({
num: 2,
action: "https://autofill",
password: {
name: "password",
autocomplete: "new-password"
}
});
await promiseFormsProcessedInSameProcess();
// 2nd form should not be filled
checkForm(2, "", "");
form.password.focus();
let pword = getFormElementByName(2, "password");
pword.focus();
await showACPopup(2, ["user1"]);
let acEvents = await waitForTelemetryEventsCondition(events => {
return events.length == 1;
}, { process: "parent", filterProps: TelemetryFilterPropsAC, clear: true }, `Wait for there to be 1 autocomplete telemetry event`);
checkACTelemetryEvent(acEvents[0], form.password, {
checkACTelemetryEvent(acEvents[0], pword, {
"hadPrevious": "0",
"login": "1",
"loginsFooter": "1"
@ -196,38 +198,33 @@ add_task(async function test_autofillAutocompletePassword_noGeneration() {
synthesizeKey("KEY_ArrowDown");
synthesizeKey("KEY_Enter");
// Can't use promiseFormsProcessedInSameProcess() when autocomplete fills the field directly.
await SimpleTest.promiseWaitForCondition(() => form.password.value == "pass1", "Check pw filled");
await SimpleTest.promiseWaitForCondition(() => pword.value == "pass1", "Check pw filled");
checkForm(2, "", "pass1");
// No autocomplete results should appear for non-empty pw fields.
await noPopupByArrowDown();
await SpecialPowers.popPrefEnv();
recreateTree(document.getElementById("form2"));
});
add_task(async function test_autofillAutocompleteUsername_noGeneration2() {
await setStoredLoginsAsync([location.origin, "https://autofill", null, "user1", "pass1"]);
// All tests below this are with generation prefs enabled.
const form = createLoginForm({
num: 2,
action: "https://autofill",
password: {
name: "password",
autocomplete: "new-password"
}
});
await promiseFormsProcessedInSameProcess();
add_task(async function test_autofillAutocompleteUsername_noGeneration2() {
await SpecialPowers.pushPrefEnv({"set": [
["signon.generation.available", true],
["signon.generation.enabled", true],
]});
// 2nd form should not be filled
checkForm(2, "", "");
form.uname.focus();
getFormElementByName(2, "uname").focus();
// No generation option on username fields.
await showACPopup(2, ["user1"]);
let acEvents = await waitForTelemetryEventsCondition(events => {
return events.length == 1;
}, { process: "parent", filterProps: TelemetryFilterPropsAC, clear: true }, `Wait for there to be 1 autocomplete telemetry event`);
checkACTelemetryEvent(acEvents[0], form.uname, {
checkACTelemetryEvent(acEvents[0], getFormElementByName(2, "uname"), {
"hadPrevious": "0",
"login": "1",
"loginsFooter": "1"
@ -237,50 +234,22 @@ add_task(async function test_autofillAutocompleteUsername_noGeneration2() {
synthesizeKey("KEY_Enter");
await promiseFormsProcessedInSameProcess();
checkForm(2, "user1", "pass1");
recreateTree(document.getElementById("form2"));
});
add_task(async function test_autofillAutocompletePassword_withGeneration() {
const formAttributesToTest = [
{
num: 2,
action: "https://autofill",
password: {
name: "password",
autocomplete: "new-password"
}
},
{
num: 3,
action: "https://autofill",
username: {
name: "username"
},
password: {
name: "password",
label: "New password"
}
}
];
const formNumbersToTest = [2, 3];
// Bug 1616356 and Bug 1548878: Recorded once per origin
let expectedPWGenTelemetryEvents = 0;
// Bug 1619498: Recorded once every time the autocomplete popup is shown
let expectedACShownTelemetryEvents = 0;
for (const formAttributes of formAttributesToTest) {
runInParent(clearGeneratedPasswords);
await setStoredLoginsAsync([location.origin, "https://autofill", null, "user1", "pass1"]);
const formNumber = formAttributes.num;
const form = createLoginForm(formAttributes);
await promiseFormsProcessedInSameProcess();
form.reset();
// This form should be filled
for (let formNumber of formNumbersToTest) {
// This form should not be filled
checkForm(formNumber, "", "");
form.password.focus();
let pword = getFormElementByName(formNumber, "password");
pword.focus();
await showACPopup(formNumber, [
"user1",
@ -293,7 +262,7 @@ add_task(async function test_autofillAutocompletePassword_withGeneration() {
let acEvents = await waitForTelemetryEventsCondition(events => {
return events.length == expectedACShownTelemetryEvents;
}, { process: "parent", filterProps: TelemetryFilterPropsAC }, `Wait for there to be ${expectedACShownTelemetryEvents} autocomplete telemetry event(s)`);
checkACTelemetryEvent(acEvents[expectedACShownTelemetryEvents - 1], form.password, {
checkACTelemetryEvent(acEvents[expectedACShownTelemetryEvents - 1], pword, {
"generatedPasswo": "1",
"hadPrevious": "0",
"login": "1",
@ -303,7 +272,7 @@ add_task(async function test_autofillAutocompletePassword_withGeneration() {
synthesizeKey("KEY_ArrowDown");
synthesizeKey("KEY_Enter");
// Can't use promiseFormsProcessedInSameProcess() when autocomplete fills the field directly.
await SimpleTest.promiseWaitForCondition(() => form.password.value == "pass1", "Check pw filled");
await SimpleTest.promiseWaitForCondition(() => pword.value == "pass1", "Check pw filled");
checkForm(formNumber, "", "pass1");
// No autocomplete results should appear for non-empty pw fields.
@ -312,10 +281,10 @@ add_task(async function test_autofillAutocompletePassword_withGeneration() {
info("Removing all logins to test auto-saving of generated passwords");
await LoginManager.removeAllUserFacingLogins();
while (form.password.value) {
while (pword.value) {
synthesizeKey("KEY_Backspace");
}
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blanked field");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blanked field");
info("This time select the generated password");
await showACPopup(formNumber, [
@ -327,7 +296,7 @@ add_task(async function test_autofillAutocompletePassword_withGeneration() {
acEvents = await waitForTelemetryEventsCondition(events => {
return events.length == expectedACShownTelemetryEvents;
}, { process: "parent", filterProps: TelemetryFilterPropsAC }, `Wait for there to be ${expectedACShownTelemetryEvents} autocomplete telemetry event(s)`);
checkACTelemetryEvent(acEvents[expectedACShownTelemetryEvents - 1], form.password, {
checkACTelemetryEvent(acEvents[expectedACShownTelemetryEvents - 1], pword, {
"generatedPasswo": "1",
"hadPrevious": "0",
"loginsFooter": "1"
@ -335,12 +304,12 @@ add_task(async function test_autofillAutocompletePassword_withGeneration() {
synthesizeKey("KEY_ArrowDown");
let storageAddPromise = promiseStorageChanged(["addLogin"]);
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Before first fill of generated pw");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Before first fill of generated pw");
synthesizeKey("KEY_Enter");
info("waiting for the password field to be filled with the generated password");
await SimpleTest.promiseWaitForCondition(() => !!form.password.value, "Check generated pw filled");
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, "After first fill of generated pw");
await SimpleTest.promiseWaitForCondition(() => !!pword.value, "Check generated pw filled");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "After first fill of generated pw");
info("Wait for generated password to be added to storage");
await storageAddPromise;
@ -349,39 +318,39 @@ add_task(async function test_autofillAutocompletePassword_withGeneration() {
let time = dateAndTimeFormatter.format(new Date(timePasswordChanged));
const LABEL_NO_USERNAME = "No username (" + time + ")";
let generatedPW = form.password.value;
let generatedPW = pword.value;
is(generatedPW.length, GENERATED_PASSWORD_LENGTH, "Check generated password length");
ok(generatedPW.match(GENERATED_PASSWORD_REGEX), "Check generated password format");
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, "After fill");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "After fill");
info("Check field is masked upon blurring");
synthesizeKey("KEY_Tab"); // blur
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "After blur");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "After blur");
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, "After shift-tab to focus again");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "After shift-tab to focus again");
// Remove selection for OS where the whole value is selected upon focus.
synthesizeKey("KEY_ArrowRight");
while (form.password.value) {
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, form.password.value);
while (pword.value) {
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, pword.value);
synthesizeKey("KEY_Backspace");
}
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blanked field");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blanked field");
info("Blur the empty field to trigger a 'change' event");
synthesizeKey("KEY_Tab"); // blur
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blur after blanking");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blur after blanking");
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Focus again after blanking");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Focus again after blanking");
info("Type a single character after blanking");
synthesizeKey("@");
info("Blur the single-character field to trigger a 'change' event");
synthesizeKey("KEY_Tab"); // blur
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blur after backspacing");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blur after backspacing");
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Focus again after backspacing");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Focus again after backspacing");
synthesizeKey("KEY_Backspace"); // Blank the field again
await showACPopup(formNumber, [
@ -393,10 +362,10 @@ add_task(async function test_autofillAutocompletePassword_withGeneration() {
synthesizeKey("KEY_ArrowDown");
synthesizeKey("KEY_ArrowDown");
synthesizeKey("KEY_Enter");
await SimpleTest.promiseWaitForCondition(() => !!form.password.value, "Check generated pw filled");
await SimpleTest.promiseWaitForCondition(() => !!pword.value, "Check generated pw filled");
// Same generated password should be used, even despite the 'change' to @ earlier.
checkForm(formNumber, "", generatedPW);
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, "Second fill of the generated pw");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "Second fill of the generated pw");
await checkTelemetryEventsPWGenUsed(expectedPWGenTelemetryEvents);
@ -407,17 +376,17 @@ add_task(async function test_autofillAutocompletePassword_withGeneration() {
info("filling the saved login to ensure the field is masked again");
while (form.password.value) {
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, form.password.value);
while (pword.value) {
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, pword.value);
synthesizeKey("KEY_Backspace");
}
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blanked field again");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blanked field again");
info("Blur the field to trigger a 'change' event again");
synthesizeKey("KEY_Tab"); // blur
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blur after blanking again");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blur after blanking again");
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Focus again after blanking again");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Focus again after blanking again");
// Remove selection for OS where the whole value is selected upon focus.
synthesizeKey("KEY_ArrowRight");
@ -429,44 +398,37 @@ add_task(async function test_autofillAutocompletePassword_withGeneration() {
synthesizeKey("KEY_ArrowDown");
synthesizeKey("KEY_Enter");
await SimpleTest.promiseWaitForCondition(() => !!form.password.value, "Check saved generated pw filled");
await SimpleTest.promiseWaitForCondition(() => !!pword.value, "Check saved generated pw filled");
// Same generated password should be used but from storage
checkForm(formNumber, "", generatedPW);
// Passwords from storage should always be masked.
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "after fill from storage");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "after fill from storage");
synthesizeKey("KEY_Tab"); // blur
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "after blur");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "after blur");
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus
LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "after shift-tab to focus again");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "after shift-tab to focus again");
info("reset initial login state with login1");
runInParent(initLogins);
addLoginsInParent([origin, "https://autofill", null, "user1", "pass1"]);
runInParent(clearGeneratedPasswords);
info("invalidate the autocomplete cache after updating storage above");
synthesizeKey("KEY_Backspace");
recreateTree(document.getElementById(`form${formNumber}`));
}
});
add_task(async function test_autofillAutocompletePassword_saveLoginDisabled() {
await setStoredLoginsAsync([location.origin, "https://autofill", null, "user1", "pass1"]);
const form = createLoginForm({
num: 2,
action: "https://autofill",
password: {
name: "password",
autocomplete: "new-password"
}
});
await promiseFormsProcessedInSameProcess();
// form should not be filled
checkForm(2, "", "");
let formOrigin = new URL(document.documentURI).origin;
is(formOrigin, origin, "Expected form origin");
await LoginManager.setLoginSavingEnabled(origin, false);
form.password.focus();
let pword = getFormElementByName(2, "password");
pword.focus();
// when login-saving is disabled for an origin, we expect no generated password row here
await showACPopup(2, ["user1"]);
@ -474,32 +436,23 @@ add_task(async function test_autofillAutocompletePassword_saveLoginDisabled() {
synthesizeKey("KEY_Escape");
await promiseACPopupClosed();
recreateTree(document.getElementById("form2"));
await LoginManager.setLoginSavingEnabled(origin, true);
});
add_task(async function test_deleteAndReselectGeneratedPassword() {
await setStoredLoginsAsync([location.origin, "https://autofill", null, "user1", "pass1"]);
const form = createLoginForm({
num: 2,
action: "https://autofill",
password: {
name: "password",
autocomplete: "new-password"
}
});
await promiseFormsProcessedInSameProcess();
info("Removing all logins to test auto-saving of generated passwords");
await LoginManager.removeAllUserFacingLogins();
// form should not be filled
checkForm(2, "", "");
let pword = getFormElementByName(2, "password");
let uname = getFormElementByName(2, "uname");
async function showAndSelectACPopupItem(index) {
form.password.focus();
if (form.password.value) {
form.password.select();
pword.focus();
if (pword.value) {
pword.select();
synthesizeKey("KEY_Backspace");
}
const autocompleteItems = await popupByArrowDown();
@ -522,15 +475,15 @@ add_task(async function test_deleteAndReselectGeneratedPassword() {
is(menuLabel, "Use a Securely Generated Password", "Check item label");
synthesizeKey("KEY_Enter");
info("waiting for the password field to be filled with the generated password");
await SimpleTest.promiseWaitForCondition(() => !!form.password.value, "Check generated pw filled");
await SimpleTest.promiseWaitForCondition(() => !!pword.value, "Check generated pw filled");
info("Wait for generated password to be added to storage");
await storagePromise;
form.uname.focus();
uname.focus();
await TestUtils.waitForTick();
is(form.password.value.length, LoginTestUtils.generation.LENGTH, "Check password looks generated");
const GENERATED_PASSWORD = form.password.value;
is(pword.value.length, LoginTestUtils.generation.LENGTH, "Check password looks generated");
const GENERATED_PASSWORD = pword.value;
savedLogins = await LoginManager.getAllLogins();
is(savedLogins.length, 1, "Check saved logins count");
@ -547,7 +500,7 @@ add_task(async function test_deleteAndReselectGeneratedPassword() {
synthesizeKey("KEY_Delete", {shiftKey: true});
await storagePromise;
form.uname.focus();
uname.focus();
await TestUtils.waitForTick();
savedLogins = await LoginManager.getAllLogins();
@ -559,11 +512,13 @@ add_task(async function test_deleteAndReselectGeneratedPassword() {
is(menuLabel, "Use a Securely Generated Password", "Check item label");
synthesizeKey("KEY_Enter");
info("waiting for the password field to be filled with the generated password");
await SimpleTest.promiseWaitForCondition(() => !!form.password.value, "Check generated pw filled");
await SimpleTest.promiseWaitForCondition(() => !!pword.value, "Check generated pw filled");
form.uname.focus();
uname.focus();
await TestUtils.waitForTick();
is(form.password.value, GENERATED_PASSWORD, "Generated password has not changed");
is(pword.value, GENERATED_PASSWORD, "Generated password has not changed");
recreateTree(document.getElementById("form2"));
});
add_task(async function test_passwordGenerationShownTelemetry() {

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

@ -10,38 +10,40 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script>
var chromeScript = runChecksAfterCommonInit();
let origin = window.location.origin;
addLoginsInParent(
[origin, "", null, "tempuser1", "temppass1", "uname", "pword"],
[origin, "", null, "tempuser2", "temppass2", "uname", "pword"]);
</script>
<p id="display"></p>
<div id="content"></div>
<div id="content">
<h1>Sign in</h1>
<input id="uname"/>
<input id="pword" type="password"/>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Login Manager: Test password field autocomplete footer with and without logins **/
add_task(async function test_no_autofill() {
await setStoredLoginsAsync(
[location.origin, "", null, "user-1", "pass-1", "uname", "pword"],
[location.origin, "", null, "user-2", "pass-2", "uname", "pword"]
);
const form = createLoginForm();
await promiseFormsProcessedInSameProcess();
let uname = document.getElementById("uname");
let pword = document.getElementById("pword");
add_task(async function test_no_autofill() {
// Make sure initial form is empty as autofill shouldn't happen in the sandboxed frame.
checkLoginForm(form.uname, "", form.pword, "");
checkLoginForm(uname, "", pword, "");
let popupState = await getPopupState();
is(popupState.open, false, "Check popup is initially closed");
});
add_task(async function test_two_logins() {
await setStoredLoginsAsync(
[location.origin, "", null, "user-1", "pass-1", "uname", "pword"],
[location.origin, "", null, "user-2", "pass-2", "uname", "pword"]
);
const form = createLoginForm();
await promiseFormsProcessedInSameProcess();
await popupBy(() => form.uname.focus());
await popupBy(() => uname.focus());
// popup on the password field should open upon focus
let results = await popupBy(() => synthesizeKey("KEY_Tab"));
@ -50,21 +52,19 @@ add_task(async function test_two_logins() {
is(popupState.selectedIndex, -1, "Check no entries are selected upon opening");
let expectedMenuItems = [
"user-1",
"user-2",
"tempuser1",
"tempuser2",
];
checkAutoCompleteResults(results, expectedMenuItems, window.location.host, "Check all menuitems are displayed correctly.");
checkLoginForm(form.uname, "", form.pword, "");
checkLoginForm(uname, "", pword, "");
let removedPromise = promiseStorageChanged(["removeAllLogins"]);
await LoginManager.removeAllUserFacingLogins();
await removedPromise;
});
add_task(async function test_zero_logins() {
// no logins stored
await setStoredLoginsAsync();
const form = createLoginForm();
await promiseFormsProcessedInSameProcess();
form.uname.focus();
uname.focus();
let shownPromise = popupBy().then(() => ok(false, "Should not have shown"));
// Popup on the password field should NOT automatically open upon focus when there are no saved logins.
@ -78,11 +78,11 @@ add_task(async function test_zero_logins() {
let popupState = await getPopupState();
is(popupState.open, false, "Check popup is still closed");
checkLoginForm(form.uname, "", form.pword, "");
checkLoginForm(uname, "", pword, "");
info("arrow down should still open the popup");
autocompleteItems = await popupByArrowDown();
checkAutoCompleteResults(autocompleteItems, [], window.location.host, "Check only footer is displayed.");
checkLoginForm(form.uname, "", form.pword, "");
checkLoginForm(uname, "", pword, "");
});
</script>
</pre>

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

@ -14,27 +14,35 @@ PWMGR_COMMON_PARENT.sendAsyncMessage("setupParent", { selfFilling: true });
SimpleTest.waitForExplicitFinish();
const chromeScript = runInParent(async function chromeSetup() {
const login1A = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
const login1B = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
const login2A = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
const login2B = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
const login2C = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
let chromeScript = runInParent(function chromeSetup() {
let login1A = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let login1B = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let login2A = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let login2B = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let login2C = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login1A.init("http://mochi.test:8888", "http://bug444968-1", null, "testuser1A", "testpass1A", "", "");
login1B.init("http://mochi.test:8888", "http://bug444968-1", null, "", "testpass1B", "", "");
login1A.init("http://mochi.test:8888", "http://bug444968-1", null,
"testuser1A", "testpass1A", "", "");
login1B.init("http://mochi.test:8888", "http://bug444968-1", null,
"", "testpass1B", "", "");
login2A.init("http://mochi.test:8888", "http://bug444968-2", null, "testuser2A", "testpass2A", "", "");
login2B.init("http://mochi.test:8888", "http://bug444968-2", null, "", "testpass2B", "", "");
login2C.init("http://mochi.test:8888", "http://bug444968-2", null, "testuser2C", "testpass2C", "", "");
login2A.init("http://mochi.test:8888", "http://bug444968-2", null,
"testuser2A", "testpass2A", "", "");
login2B.init("http://mochi.test:8888", "http://bug444968-2", null,
"", "testpass2B", "", "");
login2C.init("http://mochi.test:8888", "http://bug444968-2", null,
"testuser2C", "testpass2C", "", "");
await Services.logins.addLogins([
login1A,
login1B,
login2A,
login2B,
login2C,
]);
Services.logins.addLogin(login1A);
Services.logins.addLogin(login1B);
Services.logins.addLogin(login2A);
Services.logins.addLogin(login2B);
Services.logins.addLogin(login2C);
addMessageListener("removeLogins", function removeLogins() {
Services.logins.removeLogin(login1A);
@ -55,13 +63,13 @@ registerRunTests();
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
const DEFAULT_ORIGIN = window.location.origin;
let DEFAULT_ORIGIN = window.location.origin;
/* Test for Login Manager: 444968 (password-only forms should prefer a
* password-only login when present )
*/
async function startTest() {
const win = window.open("about:blank");
let win = window.open("about:blank");
SimpleTest.registerCleanupFunction(() => win.close());
await loadFormIntoWindow(DEFAULT_ORIGIN, `
<!-- first 3 forms have matching user+pass and pass-only logins -->

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

@ -10,6 +10,26 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script>
var chromeScript = runChecksAfterCommonInit();
var setupScript = runInParent(function setup() {
var nsLoginInfo = Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
Ci.nsILoginInfo, "init");
assert.ok(nsLoginInfo != null, "nsLoginInfo constructor");
var login1 = new nsLoginInfo("https://example.com", "", null,
"tempuser1", "temppass1", "uname", "pword");
// try/catch in case someone runs the tests manually, twice.
try {
Services.logins.addLogin(login1);
} catch (e) {
assert.ok(false, "addLogin threw: " + e);
}
});
</script>
<p id="display"></p>
<div id="content">
@ -22,7 +42,7 @@
/** Test for Login Manager: form field autofill in sandboxed documents (null principal) **/
const sandboxed = document.getElementById("sandboxed");
let sandboxed = document.getElementById("sandboxed");
let uname;
let pword;
@ -30,14 +50,10 @@ function promiseExecuteSoon() {
return new Promise(SimpleTest.executeSoon);
}
add_setup(async () => {
await setStoredLoginsAsync(["https://example.com", "", null, "tempuser1", "temppass1", "uname", "pword"]);
});
add_task(async function test_no_autofill_in_form() {
sandboxed.src = "form_basic.html";
const frameWindow = SpecialPowers.wrap(sandboxed).contentWindow;
const DOMFormHasPasswordPromise = new Promise(resolve => {
let frameWindow = SpecialPowers.wrap(sandboxed).contentWindow;
let DOMFormHasPasswordPromise = new Promise(resolve => {
SpecialPowers.addChromeEventListener("DOMFormHasPassword", function onDFHP() {
SpecialPowers.removeChromeEventListener("DOMFormHasPassword", onDFHP);
resolve();
@ -50,7 +66,7 @@ add_task(async function test_no_autofill_in_form() {
}, "Check frame is loaded");
info("frame loaded");
await DOMFormHasPasswordPromise;
const frameDoc = SpecialPowers.wrap(sandboxed).contentDocument;
let frameDoc = SpecialPowers.wrap(sandboxed).contentDocument;
uname = frameDoc.getElementById("form-basic-username");
pword = frameDoc.getElementById("form-basic-password");
@ -72,8 +88,8 @@ add_task(async function test_no_autofill_in_form() {
add_task(async function test_no_autofill_outside_form() {
sandboxed.src = "formless_basic.html";
const frameWindow = SpecialPowers.wrap(sandboxed).contentWindow;
const DOMInputPasswordAddedPromise = new Promise(resolve => {
let frameWindow = SpecialPowers.wrap(sandboxed).contentWindow;
let DOMInputPasswordAddedPromise = new Promise(resolve => {
SpecialPowers.addChromeEventListener("DOMInputPasswordAdded", function onDIPA() {
SpecialPowers.removeChromeEventListener("DOMInputPasswordAdded", onDIPA);
resolve();
@ -86,7 +102,7 @@ add_task(async function test_no_autofill_outside_form() {
}, "Check frame is loaded");
info("frame loaded");
await DOMInputPasswordAddedPromise;
const frameDoc = SpecialPowers.wrap(sandboxed).contentDocument;
let frameDoc = SpecialPowers.wrap(sandboxed).contentDocument;
uname = frameDoc.getElementById("form-basic-username");
pword = frameDoc.getElementById("form-basic-password");

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

@ -11,18 +11,69 @@
</head>
<body>
Login Manager test: autofilling when autocomplete=off
<script>
let readyPromise = registerRunTests(6);
addLoginsInParent(
[window.location.origin, "https://autocomplete2", null, "singleuser", "singlepass", "uname", "pword"]);
</script>
<p id="display"></p>
<!-- we presumably can't hide the content for this test. -->
<div id="content"></div>
<div id="content">
<!-- test single logins, with autocomplete=off set -->
<form id="form1" action="https://autocomplete2" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="pword" autocomplete="off">
<button type="submit">Submit</button>
</form>
<form id="form2" action="https://autocomplete2" onsubmit="return false;">
<input type="text" name="uname" autocomplete="off">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
<form id="form3" action="https://autocomplete2" onsubmit="return false;" autocomplete="off">
<input type="text" name="uname">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
<form id="form4" action="https://autocomplete2" onsubmit="return false;">
<input type="text" name="uname" autocomplete="off">
<input type="password" name="pword" autocomplete="off">
<button type="submit">Submit</button>
</form>
<!-- control -->
<form id="form5" action="https://autocomplete2" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
<!-- username-only form -->
<form id="form6" action="https://autocomplete2" onsubmit="return false;">
<input type="text" name="uname" autocomplete="off" id="username">
<button type="submit">Submit</button>
</form>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Login Manager: multiple login autocomplete. **/
let { ContentTaskUtils } = SpecialPowers.ChromeUtils.import(
"resource://testing-common/ContentTaskUtils.jsm"
);
// Set the pref before the document loads.
SpecialPowers.setBoolPref("signon.autofillForms.autocompleteOff", false);
SimpleTest.registerCleanupFunction(() => {
SpecialPowers.clearUserPref("signon.autofillForms.autocompleteOff");
});
// Check for expected username/password in form.
function checkFormValues(form, expectedUsername, expectedPassword) {
let uname = form.querySelector("[name='uname']");
@ -45,107 +96,73 @@ async function autoCompleteFieldsFromFirstMatch(form) {
}
add_setup(async () => {
// Set the pref before the document loads.
SpecialPowers.setBoolPref("signon.autofillForms.autocompleteOff", false);
SimpleTest.registerCleanupFunction(() => {
SpecialPowers.clearUserPref("signon.autofillForms.autocompleteOff");
});
await setStoredLoginsAsync(
[window.location.origin, "https://autocomplete", null, "singleuser", "singlepass", "uname", "pword"]
);
ok(readyPromise, "check promise is available");
await readyPromise;
listenForUnexpectedPopupShown();
});
/* Tests for autofill of single-user forms for when we honor autocomplete=off on password fields */
add_task(async function honor_password_autocomplete_off() {
const form = createLoginForm({
action: "https://autocomplete",
password: {
autocomplete: "off"
}
});
await promiseFormsProcessedInSameProcess();
add_task(async function test_form1_honor_password_autocomplete_off() {
await SimpleTest.promiseFocus(window);
// With the pref toggled off, and with autocomplete=off on the password field,
// we expect not to have autofilled this form
let form = document.getElementById("form1");
ok(form, "found form under test");
checkFormValues(form, "", "");
// ..but it should autocomplete just fine
await autoCompleteFieldsFromFirstMatch(form);
checkFormValues(form, "singleuser", "singlepass");
});
add_task(async function honor_username_autocomplete_off() {
const form = createLoginForm({
action: "https://autocomplete",
username: {
autocomplete: "off"
}
});
await promiseFormsProcessedInSameProcess();
add_task(async function test_form2_honor_password_autocomplete_off() {
await SimpleTest.promiseFocus(window);
// With the pref toggled off, and with autocomplete=off on the username field,
// we expect to have autofilled this form
let form = document.getElementById("form2");
ok(form, "found form under test");
checkFormValues(form, "singleuser", "singlepass");
});
add_task(async function honor_form_autocomplete_off() {
const form = createLoginForm({
action: "https://autocomplete",
autocomplete: "off"
});
await promiseFormsProcessedInSameProcess();
add_task(async function test_form3_honor_password_autocomplete_off() {
await SimpleTest.promiseFocus(window);
// With the pref toggled off, and with autocomplete=off on the form,
// we expect to have autofilled this form
let form = document.getElementById("form3");
ok(form, "found form under test");
checkFormValues(form, "singleuser", "singlepass");
});
add_task(async function honor_username_and_password_autocomplete_off() {
const form = createLoginForm({
action: "https://autocomplete",
username: {
autocomplete: "off"
},
password: {
autocomplete: "off"
}
});
await promiseFormsProcessedInSameProcess();
add_task(async function test_form4_honor_password_autocomplete_off() {
await SimpleTest.promiseFocus(window);
// With the pref toggled off, and autocomplete=off on the username and password field,
// we expect not to have autofilled this form
let form = document.getElementById("form4");
ok(form, "found form under test");
checkFormValues(form, "", "");
// ..but it should autocomplete just fine
await autoCompleteFieldsFromFirstMatch(form);
checkFormValues(form, "singleuser", "singlepass");
});
add_task(async function reference_form() {
const form = createLoginForm({
action: "https://autocomplete"
});
await promiseFormsProcessedInSameProcess();
add_task(async function test_form5() {
await SimpleTest.promiseFocus(window);
// (this is a control, w/o autocomplete=off, to ensure the login
// that was being suppressed would have been filled in otherwise)
let form = document.getElementById("form5");
ok(form, "found form under test");
checkFormValues(form, "singleuser", "singlepass");
});
add_task(async function honor_username_autocomplete_off_without_password() {
const form = createLoginForm({
action: "https://autocomplete",
username: {
id: "username",
autocomplete: "off"
},
password: false
});
await promiseFormsProcessedInSameProcess();
add_task(async function test_form6_honor_password_autocomplete_off() {
await SimpleTest.promiseFocus(window);
// With the pref toggled off, and with autocomplete=off on the username field
// in a username-only form, we expect to have autofilled this form
is(form.uname.value, "singleuser", `Checking form6 username is: singleuser`);
let form = document.getElementById("form6");
ok(form, "found form under test");
let uname = form.querySelector("[name='uname']");
is(uname.value, "singleuser", `Checking form6 username is: singleuser`);
});
</script>
</pre>

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

@ -12,14 +12,19 @@ Login Manager test: html5 input types (email, tel, url, etc.)
<script>
runChecksAfterCommonInit(() => startTest());
const DEFAULT_ORIGIN = window.location.origin;
let DEFAULT_ORIGIN = window.location.origin;
runInParent(async function setup() {
const login1 = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
const login2 = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
const login3 = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
const login4 = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
const login5 = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
runInParent(function setup() {
let login1 = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let login2 = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let login3 = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let login4 = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let login5 = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login1.init("http://mochi.test:8888", "http://bug600551-1", null,
"testuser@example.com", "testpass1", "", "");
@ -32,13 +37,11 @@ runInParent(async function setup() {
login5.init("http://mochi.test:8888", "http://bug600551-5", null,
"test", "test", "", "");
await Services.logins.addLogins([
login1,
login2,
login3,
login4,
login5,
]);
Services.logins.addLogin(login1);
Services.logins.addLogin(login2);
Services.logins.addLogin(login3);
Services.logins.addLogin(login4);
Services.logins.addLogin(login5);
});
</script>
@ -52,7 +55,7 @@ runInParent(async function setup() {
(Password manager not working with input type=email)
*/
async function startTest() {
const win = window.open("about:blank");
let win = window.open("about:blank");
SimpleTest.registerCleanupFunction(() => win.close());
await loadFormIntoWindow(DEFAULT_ORIGIN, `
<form id="form1" action="http://bug600551-1">

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

@ -11,18 +11,31 @@
Login Manager test: forms and logins without a username.
<script>
gTestDependsOnDeprecatedLogin = true;
runChecksAfterCommonInit(async () => {
// The first login uses a unique formActionOrigin, to check forms where no other logins
// will apply. The second login uses the normal formActionOrigin, so that we can test
runChecksAfterCommonInit(() => startTest());
runInParent(() => {
var nsLoginInfo = Components.Constructor("@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo);
// pwlogin1 uses a unique formActionOrigin, to check forms where no other logins
// will apply. pwlogin2 uses the normal formActionOrigin, so that we can test
// forms with a mix of username and non-username logins that might apply.
//
// Note: the second login is deleted at the end of the test.
await addLoginsInParent(
["http://mochi.test:8888", "http://mochi.test:1111", null, "", "1234"],
["http://mochi.test:8888", "http://mochi.test:8888", null, "", "1234"]
);
await startTest();
// Note: pwlogin2 is deleted at the end of the test.
let pwlogin1 = new nsLoginInfo();
let pwlogin2 = new nsLoginInfo();
pwlogin1.init("http://mochi.test:8888", "http://mochi.test:1111", null,
"", "1234");
pwlogin2.init("http://mochi.test:8888", "http://mochi.test:8888", null,
"", "1234");
Services.logins.addLogin(pwlogin1);
Services.logins.addLogin(pwlogin2);
});
let DEFAULT_ORIGIN = window.location.origin;
</script>
<p id="display"></p>
@ -31,11 +44,10 @@ runChecksAfterCommonInit(async () => {
<pre id="test">
<script class="testbody" type="text/javascript">
const DEFAULT_ORIGIN = window.location.origin;
/** Test for Login Manager: password-only logins **/
async function startTest() {
const win = window.open("about:blank");
let win = window.open("about:blank");
SimpleTest.registerCleanupFunction(() => win.close());
await loadFormIntoWindow(DEFAULT_ORIGIN, `
<!-- simple form: no username field, 1 password field -->

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

@ -77,31 +77,32 @@
{expectedDialogs: 1, test: testAnonymousCredentials},
{expectedDialogs: 0, test: testAnonymousNoAuth}];
const mm = runInParent(() => {
let mm = runInParent(() => {
const { classes: parentCc, interfaces: parentCi } = Components;
const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
let {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
const channel = NetUtil.newChannel({
let channel = NetUtil.newChannel({
uri: "http://example.com",
loadUsingSystemPrincipal: true,
});
const pps = parentCc["@mozilla.org/network/protocol-proxy-service;1"].
let pps = parentCc["@mozilla.org/network/protocol-proxy-service;1"].
getService(parentCi.nsIProtocolProxyService);
pps.asyncResolve(channel, 0, {
async onProxyAvailable(req, uri, pi, status) {
const mozproxy = "moz-proxy://" + pi.host + ":" + pi.port;
const login1 = parentCc["@mozilla.org/login-manager/loginInfo;1"].
onProxyAvailable(req, uri, pi, status) {
let mozproxy = "moz-proxy://" + pi.host + ":" + pi.port;
let login = parentCc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(parentCi.nsILoginInfo);
login1.init(mozproxy, null, "proxy_realm", "proxy_user", "proxy_pass",
login.init(mozproxy, null, "proxy_realm", "proxy_user", "proxy_pass",
"", "");
Services.logins.addLogin(login);
const login2 = parentCc["@mozilla.org/login-manager/loginInfo;1"].
let login2 = parentCc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(parentCi.nsILoginInfo);
login2.init("http://mochi.test:8888", null, "mochirealm", "user1name",
"user1pass", "", "");
await Services.logins.addLogins([login1, login2]);
Services.logins.addLogin(login2);
sendAsyncMessage("setupDone");
},
@ -115,10 +116,10 @@
sendAsyncMessage("prepareForNextTestDone");
});
const modalType = Services.prefs.getIntPref(
let modalType = Services.prefs.getIntPref(
"prompts.modalType.httpAuth"
);
const authPromptIsCommonDialog =
let authPromptIsCommonDialog =
modalType === Services.prompt.MODAL_TYPE_WINDOW
|| (modalType === Services.prompt.MODAL_TYPE_TAB
&& Services.prefs.getBoolPref(
@ -126,7 +127,7 @@
false
));
const dialogObserverTopic = authPromptIsCommonDialog
let dialogObserverTopic = authPromptIsCommonDialog
? "common-dialog-loaded" : "tabmodal-dialog-loaded";
function dialogObserver(subj, topic, data) {
@ -135,7 +136,7 @@
.getElementById("commonDialog")
.acceptDialog();
} else {
const prompt = subj.ownerGlobal.gBrowser.selectedBrowser
let prompt = subj.ownerGlobal.gBrowser.selectedBrowser
.tabModalPromptBox.getPrompt(subj);
prompt.Dialog.ui.button0.click(); // Accept button
}

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

@ -11,88 +11,99 @@
</head>
<body>
Login Manager test: autocomplete due to multiple matching logins
<script>
runChecksAfterCommonInit(false);
let origin = window.location.origin;
addLoginsInParent(
[origin, "https://autocomplete:8888", null, "name", "pass", "uname", "pword"],
[origin, "https://autocomplete:8888", null, "Name", "Pass", "uname", "pword"],
[origin, "https://autocomplete:8888", null, "USER", "PASS", "uname", "pword"]);
</script>
<p id="display"></p>
<!-- we presumably can't hide the content for this test. -->
<div id="content"></div>
<div id="content">
<!-- form1 tests multiple matching logins -->
<form id="form1" action="https://autocomplete:8888/formtest.js" onsubmit="return false;">
<input type="text" name="uname">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Login Manager: autocomplete due to multiple matching logins **/
add_setup(async () => {
await addLoginsInParent(
[location.origin, "https://autocomplete:8888", null, "name", "pass", "uname", "pword"],
[location.origin, "https://autocomplete:8888", null, "Name", "Pass", "uname", "pword"],
[location.origin, "https://autocomplete:8888", null, "USER", "PASS", "uname", "pword"]
);
})
const uname = getFormElementByName(1, "uname");
const pword = getFormElementByName(1, "pword");
// Restore the form to the default state.
function restoreForm() {
uname.value = "";
pword.value = "";
uname.focus();
}
add_task(async function test_empty_first_entry() {
const form = createLoginForm({
action: "https://autocomplete:8888"
});
/* test 1 */
// Make sure initial form is empty.
checkLoginForm(form.uname, "", form.pword, "");
checkLoginForm(uname, "", pword, "");
// Trigger autocomplete popup
form.uname.focus();
restoreForm();
let popupState = await getPopupState();
is(popupState.open, false, "Check popup is initially closed");
const { items } = await openPopupOn(form.uname);
const { items } = await openPopupOn(uname);
popupState = await getPopupState();
is(popupState.selectedIndex, -1, "Check no entries are selected");
checkAutoCompleteResults(items, ["name", "Name", "USER"], "example.com", "initial");
// Check first entry
const index0Promise = notifySelectedIndex(0);
let index0Promise = notifySelectedIndex(0);
synthesizeKey("KEY_ArrowDown");
await index0Promise;
checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update
checkLoginForm(uname, "", pword, ""); // value shouldn't update
synthesizeKey("KEY_Enter");
await promiseFormsProcessedInSameProcess();
checkLoginForm(form.uname, "name", form.pword, "pass");
checkLoginForm(uname, "name", pword, "pass");
});
add_task(async function test_empty_second_entry() {
const form = createLoginForm({
action: "https://autocomplete:8888"
});
await openPopupOn(form.uname);
restoreForm();
await openPopupOn(uname);
synthesizeKey("KEY_ArrowDown"); // first
synthesizeKey("KEY_ArrowDown"); // second
synthesizeKey("KEY_Enter");
await promiseFormsProcessedInSameProcess();
checkLoginForm(form.uname, "Name", form.pword, "Pass");
checkLoginForm(uname, "Name", pword, "Pass");
});
add_task(async function test_empty_third_entry() {
const form = createLoginForm({
action: "https://autocomplete:8888"
});
await openPopupOn(form.uname);
restoreForm();
await openPopupOn(uname);
synthesizeKey("KEY_ArrowDown"); // first
synthesizeKey("KEY_ArrowDown"); // second
synthesizeKey("KEY_ArrowDown"); // third
synthesizeKey("KEY_Enter");
await promiseFormsProcessedInSameProcess();
checkLoginForm(form.uname, "USER", form.pword, "PASS");
checkLoginForm(uname, "USER", pword, "PASS");
});
add_task(async function test_preserve_matching_username_case() {
const form = createLoginForm({
action: "https://autocomplete:8888"
});
await promiseFormsProcessedInSameProcess();
restoreForm();
await openPopupOn(uname, { inputValue: "user" });
await openPopupOn(form.uname, { inputValue: "user" });
// Check that we don't clobber user-entered text when tabbing away
// (even with no autocomplete entry selected)
synthesizeKey("KEY_Tab");
await promiseFormsProcessedInSameProcess();
checkLoginForm(form.uname, "user", form.pword, "PASS");
checkLoginForm(uname, "user", pword, "PASS");
});
</script>
</pre>

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

@ -12,17 +12,21 @@ Login Manager test: form with JS submit action
<script>
runChecksAfterCommonInit(() => startTest());
const origin = window.location.origin;
runInParent(function setup() {
let jslogin = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
jslogin.init("http://mochi.test:8888", "javascript:", null,
"jsuser", "jspass123", "uname", "pword");
Services.logins.addLogin(jslogin);
});
let DEFAULT_ORIGIN = window.location.origin;
/** Test for Login Manager: JS action URL **/
async function startTest() {
await addLoginsInParent(
[origin, "javascript:", null, "jsuser", "jspass123", "uname", "pword"]
);
const win = window.open("about:blank");
let win = window.open("about:blank");
SimpleTest.registerCleanupFunction(() => win.close());
await loadFormIntoWindow(origin, `
await loadFormIntoWindow(DEFAULT_ORIGIN, `
<form id='form1' action='javascript:alert("never shows")'> 1
<input name="uname">
<input name="pword" type="password">

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

@ -8,49 +8,91 @@
<script type="text/javascript" src="pwmgr_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<body onload="onNewEvent(event)">
Login Manager test: input events should fire.
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script>
add_setup(async () => {
await setStoredLoginsAsync(
[location.origin, location.origin, null, "testuser", "testpass", "uname", "pword"]
);
})
gTestDependsOnDeprecatedLogin = true;
runChecksAfterCommonInit();
add_task(async function username_events() {
return new Promise(resolve => {
let inputFired = false;
const form = createLoginForm();
form.uname.oninput = e => {
is(e.target.value, "testuser", "Should get 'testuser' as value in input event");
inputFired = true;
};
form.uname.onchange = e => {
ok(inputFired, "Should get input event before change event for username field.");
is(e.target.value, "testuser", "Should get 'testuser' as value in change event");
resolve();
};
})
})
SimpleTest.requestFlakyTimeout("untriaged");
/** Test for Login Manager: form fill, should get input events. **/
var usernameInputFired = false;
var passwordInputFired = false;
var usernameChangeFired = false;
var passwordChangeFired = false;
var onloadFired = false;
function onNewEvent(e) {
info("Got " + e.type + " event.");
if (e.type == "load") {
onloadFired = true;
} else if (e.type == "input") {
if (e.target.name == "uname") {
is(e.target.value, "testuser", "Should get 'testuser' as username");
ok(!usernameInputFired, "Should not have gotten an input event for the username field yet.");
usernameInputFired = true;
} else if (e.target.name == "pword") {
is(e.target.value, "testpass", "Should get 'testpass' as password");
ok(!passwordInputFired, "Should not have gotten an input event for the password field yet.");
passwordInputFired = true;
}
} else if (e.type == "change") {
if (e.target.name == "uname") {
is(e.target.value, "testuser", "Should get 'testuser' as username");
ok(usernameInputFired, "Should get input event before change event for username field.");
ok(!usernameChangeFired, "Should not have gotten a change event for the username field yet.");
usernameChangeFired = true;
} else if (e.target.name == "pword") {
is(e.target.value, "testpass", "Should get 'testpass' as password");
ok(passwordInputFired, "Should get input event before change event for password field.");
ok(!passwordChangeFired, "Should not have gotten a change event for the password field yet.");
passwordChangeFired = true;
}
}
if (onloadFired && usernameInputFired && passwordInputFired && usernameChangeFired && passwordChangeFired) {
ok(true, "All events fired as expected, we're done.");
SimpleTest.finish();
}
}
SimpleTest.registerCleanupFunction(function cleanup() {
clearTimeout(timeout);
getFormElementByName(1, "uname").removeAttribute("oninput");
getFormElementByName(1, "pword").removeAttribute("oninput");
getFormElementByName(1, "uname").removeAttribute("onchange");
getFormElementByName(1, "pword").removeAttribute("onchange");
document.body.removeAttribute("onload");
});
var timeout = setTimeout(function() {
ok(usernameInputFired, "Username input event should have fired by now.");
ok(passwordInputFired, "Password input event should have fired by now.");
ok(usernameChangeFired, "Username change event should have fired by now.");
ok(passwordChangeFired, "Password change event should have fired by now.");
ok(onloadFired, "Window load event should have fired by now.");
ok(false, "Not all events fired yet.");
SimpleTest.finish();
}, 10000);
add_task(async function password_events() {
return new Promise(resolve => {
let inputFired = false;
const form = createLoginForm();
form.pword.oninput = e => {
is(e.target.value, "testpass", "Should get 'testpass' as value in input event");
inputFired = true;
};
form.pword.onchange = e => {
ok(inputFired, "Should get input event before change event for password field.");
is(e.target.value, "testpass", "Should get 'testpass' as value in change event");
resolve();
};
})
})
</script>
<p id="display"></p>
<div id="content" style="display: none">
<form id="form1" action="formtest.js">
<p>This is form 1.</p>
<input type="text" name="uname" oninput="onNewEvent(event)" onchange="onNewEvent(event)">
<input type="password" name="pword" oninput="onNewEvent(event)" onchange="onNewEvent(event)">
<button type="submit">Submit</button>
<button type="reset"> Reset </button>
</form>
</div>
<pre id="test"></pre>
</body>
</html>

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

@ -10,7 +10,7 @@
</head>
<body>
<script type="application/javascript">
const readyPromise = registerRunTests();
let readyPromise = registerRunTests();
const DEFAULT_ORIGIN = window.location.origin;
@ -20,14 +20,14 @@ function removeAllUserFacingLoginsInParent() {
});
}
async function add2logins() {
function add2logins() {
removeAllUserFacingLoginsInParent();
await addLoginsInParent([DEFAULT_ORIGIN, DEFAULT_ORIGIN, null, "real••••user", "pass1", "", ""], [DEFAULT_ORIGIN, DEFAULT_ORIGIN, null, "user2", "pass2", "", ""]);
addLoginsInParent([DEFAULT_ORIGIN, DEFAULT_ORIGIN, null, "real••••user", "pass1", "", ""], [DEFAULT_ORIGIN, DEFAULT_ORIGIN, null, "user2", "pass2", "", ""]);
}
async function addSingleLogin() {
function addSingleLogin() {
removeAllUserFacingLoginsInParent();
await addLoginsInParent([DEFAULT_ORIGIN, DEFAULT_ORIGIN, null, "real••••user", "pass1", "", ""])
addLoginsInParent([DEFAULT_ORIGIN, DEFAULT_ORIGIN, null, "real••••user", "pass1", "", ""])
}
/**
@ -37,14 +37,14 @@ async function addSingleLogin() {
function generateTestCases(test) {
const MUNGE_CHARS = ["*", ".", "•"];
const nothingToReplace = Object.values(test).every(value => typeof value !== "string" || !value.includes("!"));
let nothingToReplace = Object.values(test).every(value => typeof value !== "string" || !value.includes("!"));
if (nothingToReplace) {
return test;
};
return MUNGE_CHARS.map(char => {
const newTest = {};
for (const [propName, val] of Object.entries(test)) {
let newTest = {};
for (let [propName, val] of Object.entries(test)) {
if (typeof val === "string") {
newTest[propName] = val.replace(/!/g, char);
} else {
@ -54,7 +54,7 @@ async function addSingleLogin() {
return newTest;
})};
const loadPromise = new Promise(resolve => {
let loadPromise = new Promise(resolve => {
document.addEventListener("DOMContentLoaded", () => {
resolve();
});
@ -101,14 +101,14 @@ add_task(async function test_new_logins() {
expected: "*.•*.•*.•*.•*.•*.•",
},
].flatMap(generateTestCases);
for (const tc of TEST_CASES) {
for (let tc of TEST_CASES) {
info("Starting testcase: " + JSON.stringify(tc));
// Create a new window for each test case, because if we instead try to use
// the same window and change the page using window.location, that will trigger
// an onLocationChange event, which can trigger unwanted FormSubmit outside of
// clicking the submit button in each test document.
const win = window.open("about:blank");
const html = `
let win = window.open("about:blank");
let html = `
<form id="form1" onsubmit="return false;">
<input type="text" name="uname" value="${tc.username}">
<input type="password" name="pword" value="thepassword">
@ -116,25 +116,25 @@ add_task(async function test_new_logins() {
</form>`;
await loadFormIntoWindow(DEFAULT_ORIGIN, html, win);
await SpecialPowers.spawn(win, [html], function(contentHtml) {
const doc = this.content.document;
for (const field of doc.querySelectorAll("input")) {
const actualValue = field.value;
let doc = this.content.document;
for (let field of doc.querySelectorAll("input")) {
let actualValue = field.value;
field.value = "";
SpecialPowers.wrap(field).setUserInput(actualValue);
}
});
await SpecialPowers.spawn(win, [tc], function(testcase) {
const doc = this.content.document;
let doc = this.content.document;
Assert.equal(doc.querySelector("[name='uname']").value, testcase.username, "Checking for filled username");
});
// Check data sent via PasswordManager:onFormSubmit
const processedPromise = getSubmitMessage();
let processedPromise = getSubmitMessage();
await SpecialPowers.spawn(win, [], function() {
this.content.document.getElementById("submitBtn").click();
});
const { data } = await processedPromise;
let { data } = await processedPromise;
info("Got submitted result: " + JSON.stringify(data));
if (tc.expected === null) {
@ -177,14 +177,14 @@ add_task(async function test_no_save_dialog_when_password_is_fully_munged() {
},
].flatMap(generateTestCases);
for (const tc of TEST_CASES) {
for (let tc of TEST_CASES) {
info("Starting testcase: " + tc.testName)
// Create a new window for each test case, because if we instead try to use
// the same window and change the page using window.location, that will trigger
// an onLocationChange event, which can trigger unwanted FormSubmit outside of
// clicking the submit button in each test document.
const win = window.open("about:blank");
const html = `
let win = window.open("about:blank");
let html = `
<form id="form1" onsubmit="return false;">
<input type="text" name="uname" value="username">
<input type="password" name="pword" value="${tc.password}">
@ -192,19 +192,19 @@ add_task(async function test_no_save_dialog_when_password_is_fully_munged() {
</form>`;
await loadFormIntoWindow(DEFAULT_ORIGIN, html, win);
await SpecialPowers.spawn(win, [html], function(contentHtml) {
const doc = this.content.document;
for (const field of doc.querySelectorAll("input")) {
const actualValue = field.value;
let doc = this.content.document;
for (let field of doc.querySelectorAll("input")) {
let actualValue = field.value;
field.value = "";
SpecialPowers.wrap(field).setUserInput(actualValue);
}
});
await SpecialPowers.spawn(win, [tc], function(testcase) {
const doc = this.content.document;
let doc = this.content.document;
Assert.equal(doc.querySelector("[name='pword']").value, testcase.password, "Checking for filled password");
});
const formSubmitListener = SpecialPowers.spawn(win, [], function() {
let formSubmitListener = SpecialPowers.spawn(win, [], function() {
return new Promise(resolve => {
this.content.windowRoot.addEventListener(
"PasswordManager:ShowDoorhanger",
@ -220,7 +220,7 @@ add_task(async function test_no_save_dialog_when_password_is_fully_munged() {
this.content.document.getElementById("submitBtn").click();
});
const dialogRequested = await formSubmitListener;
let dialogRequested = await formSubmitListener;
is(dialogRequested, tc.shouldShowPrompt, "Verify 'show save/update prompt' message sent to parent process");
@ -232,18 +232,18 @@ add_task(async function test_no_save_dialog_when_password_is_fully_munged() {
add_task(async function test_no_autofill_munged_username_matching_password() {
// run this test with 2 matching logins from this origin so we don't autofill
await add2logins();
const allLogins = await LoginManager.getAllLogins();
const matchingLogins = Array.prototype.filter.call(allLogins, l => l.origin == DEFAULT_ORIGIN);
let allLogins = await LoginManager.getAllLogins();
let matchingLogins = Array.prototype.filter.call(allLogins, l => l.origin == DEFAULT_ORIGIN);
is(matchingLogins.length, 2, "Expected number of matching logins");
const bulletLogin = matchingLogins.find(l => l.username == "real••••user");
let bulletLogin = matchingLogins.find(l => l.username == "real••••user");
ok(bulletLogin, "Found the real••••user login");
const timesUsed = bulletLogin.timesUsed;
const guid = bulletLogin.guid;
let timesUsed = bulletLogin.timesUsed;
let guid = bulletLogin.guid;
const win = window.open("about:blank");
const html =
let win = window.open("about:blank");
let html =
`<form id="form1" onsubmit="return false;">
<input type="text" name="uname" value="">
<input type="password" name="pword" value="">
@ -251,36 +251,36 @@ add_task(async function test_no_autofill_munged_username_matching_password() {
</form>`;
await loadFormIntoWindow(DEFAULT_ORIGIN, html, win);
await SpecialPowers.spawn(win, [html], function(contentHtml) {
const doc = this.content.document;
for (const field of doc.querySelectorAll("input")) {
const actualValue = field.value;
let doc = this.content.document;
for (let field of doc.querySelectorAll("input")) {
let actualValue = field.value;
field.value = "";
SpecialPowers.wrap(field).setUserInput(actualValue);
}
});
await SpecialPowers.spawn(win, [], function() {
const doc = this.content.document;
let doc = this.content.document;
Assert.equal(doc.querySelector("[name='uname']").value, "", "Check username didn't get autofilled");
SpecialPowers.wrap(doc.querySelector("[name='uname']")).setUserInput("real••••user");
SpecialPowers.wrap(doc.querySelector("[name='pword']")).setUserInput("pass1");
});
// we shouldn't get the save password doorhanger...
const popupShownPromise = noPopupBy();
let popupShownPromise = noPopupBy();
// Check data sent via PasswordManager:onFormSubmit
const processedPromise = getSubmitMessage();
let processedPromise = getSubmitMessage();
await SpecialPowers.spawn(win, [], function() {
this.content.document.getElementById("submitBtn").click();
});
const { data } = await processedPromise;
let { data } = await processedPromise;
info("Got submitted result: " + JSON.stringify(data));
is(data.usernameField, null, "Check usernameField");
const updatedLogins = await LoginManager.getAllLogins();
const updatedLogin = Array.prototype.find.call(updatedLogins, l => l.guid == guid);
let updatedLogins = await LoginManager.getAllLogins();
let updatedLogin = Array.prototype.find.call(updatedLogins, l => l.guid == guid);
ok(updatedLogin, "Got the login via guid");
is(updatedLogin.timesUsed, timesUsed + 1, "timesUsed was incremented");
@ -295,19 +295,19 @@ add_task(async function test_autofill_munged_username_matching_password() {
// only a single matching login so we autofill the username
await addSingleLogin();
const allLogins = await LoginManager.getAllLogins();
const matchingLogins = Array.prototype.filter.call(allLogins, l => l.origin == DEFAULT_ORIGIN);
let allLogins = await LoginManager.getAllLogins();
let matchingLogins = Array.prototype.filter.call(allLogins, l => l.origin == DEFAULT_ORIGIN);
is(matchingLogins.length, 1, "Expected number of matching logins");
info("matched login: " + matchingLogins[0].username);
const bulletLogin = matchingLogins.find(l => l.username == "real••••user");
let bulletLogin = matchingLogins.find(l => l.username == "real••••user");
ok(bulletLogin, "Found the real••••user login");
const timesUsed = bulletLogin.timesUsed;
const guid = bulletLogin.guid;
let timesUsed = bulletLogin.timesUsed;
let guid = bulletLogin.guid;
const win = window.open("about:blank");
const html =
let win = window.open("about:blank");
let html =
`<form id="form1" onsubmit="return false;">
<input type="text" name="uname" value="">
<input type="password" name="pword" value="">
@ -315,35 +315,35 @@ add_task(async function test_autofill_munged_username_matching_password() {
</form>`;
await loadFormIntoWindow(DEFAULT_ORIGIN, html, win);
await SpecialPowers.spawn(win, [html], function(contentHtml) {
const doc = this.content.document;
for (const field of doc.querySelectorAll("input")) {
const actualValue = field.value;
let doc = this.content.document;
for (let field of doc.querySelectorAll("input")) {
let actualValue = field.value;
field.value = "";
SpecialPowers.wrap(field).setUserInput(actualValue);
}
});
await SpecialPowers.spawn(win, [], function() {
const doc = this.content.document;
let doc = this.content.document;
Assert.equal(doc.querySelector("[name='uname']").value, "real••••user", "Check username did get autofilled");
doc.querySelector("[name='pword']").setUserInput("pass1");
});
// we shouldn't get the save/update password doorhanger as it didn't change
const popupShownPromise = noPopupBy();
let popupShownPromise = noPopupBy();
// Check data sent via PasswordManager:onFormSubmit
const processedPromise = getSubmitMessage();
let processedPromise = getSubmitMessage();
await SpecialPowers.spawn(win, [], function() {
this.content.document.getElementById("submitBtn").click();
});
const { data } = await processedPromise;
let { data } = await processedPromise;
info("Got submitted result: " + JSON.stringify(data));
is(data.usernameField, null, "Check usernameField");
const updatedLogins = await LoginManager.getAllLogins();
const updatedLogin = Array.prototype.find.call(updatedLogins, l => l.guid == guid);
let updatedLogins = await LoginManager.getAllLogins();
let updatedLogin = Array.prototype.find.call(updatedLogins, l => l.guid == guid);
ok(updatedLogin, "Got the login via guid");
is(updatedLogin.timesUsed, timesUsed + 1, "timesUsed was incremented");

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

@ -23,20 +23,31 @@ Login Manager test: primary password.
// Force parent to not look for tab-modal prompts, as they're not used for auth prompts.
modalType = Ci.nsIPrompt.MODAL_TYPE_WINDOW;
const exampleCom = "https://example.com/tests/toolkit/components/passwordmgr/test/mochitest/";
const exampleOrg = "https://example.org/tests/toolkit/components/passwordmgr/test/mochitest/";
var exampleCom = "https://example.com/tests/toolkit/components/passwordmgr/test/mochitest/";
var exampleOrg = "https://example.org/tests/toolkit/components/passwordmgr/test/mochitest/";
gTestDependsOnDeprecatedLogin = true;
const chromeScript = runChecksAfterCommonInit();
var chromeScript = runChecksAfterCommonInit();
const win = window.open("about:blank");
runInParent(() => {
var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo);
var login1 = new nsLoginInfo();
var login2 = new nsLoginInfo();
login1.init("https://example.com", "https://example.com", null,
"user1", "pass1", "uname", "pword");
login2.init("https://example.org", "https://example.org", null,
"user2", "pass2", "uname", "pword");
Services.logins.addLogin(login1);
Services.logins.addLogin(login2);
});
let win = window.open("about:blank");
SimpleTest.registerCleanupFunction(() => win.close());
add_setup(async () => {
await addLoginsInParent(
["https://example.com", "https://example.com", null, "user1", "pass1", "uname", "pword"],
["https://example.org", "https://example.org", null, "user2", "pass2", "uname", "pword"]
);
ok(await isLoggedIn(), "should be initially logged in (no PP)");
enablePrimaryPassword();
ok(!await isLoggedIn(), "should be logged out after setting PP");
@ -44,7 +55,7 @@ add_setup(async () => {
add_task(async function test_1() {
// Trigger a MP prompt via the API
const state = {
var state = {
msg: "Please enter your Primary Password.",
title: "the title",
textValue: "",
@ -59,13 +70,13 @@ add_task(async function test_1() {
focused: "passField",
defButton: "button0",
};
const action = {
var action = {
buttonClick: "ok",
passField: LoginTestUtils.primaryPassword.primaryPassword,
};
const promptDone = handlePrompt(state, action);
var promptDone = handlePrompt(state, action);
const logins = await LoginManager.getAllLogins();
var logins = await LoginManager.getAllLogins();
await promptDone;
is(logins.length, 3, "expected number of logins");
@ -77,7 +88,7 @@ add_task(async function test_1() {
add_task(async function test_2() {
// Try again but click cancel.
const state = {
var state = {
msg: "Please enter your Primary Password.",
title: "the title",
textValue: "",
@ -92,19 +103,19 @@ add_task(async function test_2() {
focused: "passField",
defButton: "button0",
};
const action = {
var action = {
buttonClick: "cancel",
};
const promptDone = handlePrompt(state, action);
var promptDone = handlePrompt(state, action);
const logins = await LoginManager.getAllLogins().catch(() => {});
var logins = await LoginManager.getAllLogins().catch(() => {});
await promptDone;
is(logins, undefined, "shouldn't have gotten logins");
ok(!await isLoggedIn(), "should still be logged out");
});
add_task(async function test_3() {
const state = {
var state = {
msg: "Please enter your Primary Password.",
title: "the title",
textValue: "",
@ -119,13 +130,13 @@ add_task(async function test_3() {
focused: "passField",
defButton: "button0",
};
const action = {
var action = {
buttonClick: "ok",
passField: LoginTestUtils.primaryPassword.primaryPassword,
};
const promptDone = handlePrompt(state, action);
var promptDone = handlePrompt(state, action);
const fillPromise = promiseFormsProcessed();
var fillPromise = promiseFormsProcessed();
info("Load a single window to trigger a MP");
await SimpleTest.promiseFocus(win, true);
@ -139,8 +150,8 @@ add_task(async function test_3() {
// check contents of win fields
await SpecialPowers.spawn(win, [], function() {
const u = this.content.document.getElementById("userfield");
const p = this.content.document.getElementById("passfield");
var u = this.content.document.getElementById("userfield");
var p = this.content.document.getElementById("passfield");
Assert.equal(u.value, "user1", "checking expected user to have been filled in");
Assert.equal(p.value, "pass1", "checking expected pass to have been filled in");
u.value = "";
@ -153,7 +164,7 @@ add_task(async function test_3() {
});
add_task(async function test_4() {
const state = {
var state = {
msg: "Please enter your Primary Password.",
title: "the title",
textValue: "",
@ -168,10 +179,10 @@ add_task(async function test_4() {
focused: "passField",
defButton: "button0",
};
let action = {
var action = {
buttonClick: "none",
};
const promptDone = handlePrompt(state, action);
var promptDone = handlePrompt(state, action);
// first part of loading 2 MP-triggering windows
await SimpleTest.promiseFocus(win);
@ -181,8 +192,8 @@ add_task(async function test_4() {
// check contents of win fields
await SpecialPowers.spawn(win, [], function() {
const u = this.content.document.getElementById("userfield");
const p = this.content.document.getElementById("passfield");
var u = this.content.document.getElementById("userfield");
var p = this.content.document.getElementById("passfield");
Assert.equal(u.value, "", "checking expected empty user");
Assert.equal(p.value, "", "checking expected empty pass");
});
@ -197,10 +208,10 @@ add_task(async function test_4() {
// Since the Primary Password prompt is open, we can't focus another tab
// to load the second form. Instead, we load the same form into an iframe.
const url = exampleOrg + "subtst_primary_pass.html";
let url = exampleOrg + "subtst_primary_pass.html";
await SpecialPowers.spawn(win, [url], async function(urlF) {
const iframe = this.content.document.querySelector("iframe");
const loadPromise = new Promise(resolve => {
let iframe = this.content.document.querySelector("iframe");
var loadPromise = new Promise(resolve => {
iframe.addEventListener("load", function onload() {
resolve();
}, { once: true });
@ -218,8 +229,8 @@ add_task(async function test_4() {
// (incorrectly) fill in the form. Note, we cannot use setTimeout()
// here because the modal window suspends all window timers. Instead we
// must use a chrome script to use nsITimer directly.
const chromeURL = SimpleTest.getTestFileURL("chrome_timeout.js");
const script = SpecialPowers.loadChromeScript(chromeURL);
let chromeURL = SimpleTest.getTestFileURL("chrome_timeout.js");
let script = SpecialPowers.loadChromeScript(chromeURL);
script.addMessageListener("ready", _ => {
script.sendAsyncMessage("setTimeout", { delay: 500 });
});
@ -231,10 +242,10 @@ add_task(async function test_4() {
// check contents of iframe fields
await SpecialPowers.spawn(win, [], function() {
const iframe = this.content.document.querySelector("iframe");
const frameDoc = iframe.contentDocument;
const u = frameDoc.getElementById("userfield");
const p = frameDoc.getElementById("passfield");
let iframe = this.content.document.querySelector("iframe");
let frameDoc = iframe.contentDocument;
var u = frameDoc.getElementById("userfield");
var p = frameDoc.getElementById("passfield");
Assert.equal(u.value, "", "checking expected empty user");
Assert.equal(p.value, "", "checking expected empty pass");
});
@ -243,7 +254,7 @@ add_task(async function test_4() {
ok(!await isLoggedIn(), "should be logged out");
// Ok, now enter the MP. The MP prompt is already up.
const fillPromise = promiseFormsProcessed(2);
var fillPromise = promiseFormsProcessed(2);
// fill existing MP dialog with MP.
action = {
@ -261,8 +272,8 @@ add_task(async function test_4() {
// check contents of win fields
await SpecialPowers.spawn(win, [], function() {
const u = this.content.document.getElementById("userfield");
const p = this.content.document.getElementById("passfield");
var u = this.content.document.getElementById("userfield");
var p = this.content.document.getElementById("passfield");
Assert.equal(u.value, "user2", "checking expected user to have been filled in");
Assert.equal(p.value, "pass2", "checking expected pass to have been filled in");
@ -273,10 +284,10 @@ add_task(async function test_4() {
// check contents of iframe fields
await SpecialPowers.spawn(win, [], function() {
const iframe = this.content.document.querySelector("iframe");
const frameDoc = iframe.contentDocument;
const u = frameDoc.getElementById("userfield");
const p = frameDoc.getElementById("passfield");
let iframe = this.content.document.querySelector("iframe");
let frameDoc = iframe.contentDocument;
var u = frameDoc.getElementById("userfield");
var p = frameDoc.getElementById("passfield");
Assert.equal(u.value, "user2", "checking expected user to have been filled in");
Assert.equal(p.value, "pass2", "checking expected pass to have been filled in");

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

@ -47,15 +47,44 @@ let prompter1 = new PrompterProxy(prompterParent);
const defaultTitle = "the title";
const defaultMsg = "the message";
function initLogins() {
var login1, login2A, login2B, login2C, login2D, login2E;
login1 = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login2A = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login2B = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login2C = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login2D = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login2E = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login1.init("http://example.com", null, "http://example.com",
"", "examplepass", "", "");
login2A.init("http://example2.com", null, "http://example2.com",
"user1name", "user1pass", "", "");
login2B.init("http://example2.com", null, "http://example2.com",
"user2name", "user2pass", "", "");
login2C.init("http://example2.com", null, "http://example2.com",
"user3.name@host", "user3pass", "", "");
login2D.init("http://example2.com", null, "http://example2.com",
"100@beef", "user3pass", "", "");
login2E.init("http://example2.com", null, "http://example2.com",
"100%beef", "user3pass", "", "");
Services.logins.addLogin(login1);
Services.logins.addLogin(login2A);
Services.logins.addLogin(login2B);
Services.logins.addLogin(login2C);
Services.logins.addLogin(login2D);
Services.logins.addLogin(login2E);
}
add_setup(async () => {
await addLoginsInParent(
["http://example.com", null, "http://example.com", "", "examplepass", "", ""],
["http://example2.com", null, "http://example2.com", "user1name", "user1pass", "", ""],
["http://example2.com", null, "http://example2.com", "user2name", "user2pass", "", ""],
["http://example2.com", null, "http://example2.com", "user3.name@host", "user3pass", "", ""],
["http://example2.com", null, "http://example2.com", "100@beef", "user3pass", "", ""],
["http://example2.com", null, "http://example2.com", "100%beef", "user3pass", "", ""]
);
runInParent(initLogins);
});
add_task(async function test_prompt_accept() {

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

@ -24,18 +24,49 @@ modalType = authPromptModalType;
const AUTHENTICATE_PATH = new URL("authenticate.sjs", window.location.href).pathname;
add_setup(async () => {
await addLoginsInParent(
["http://mochi.test:8888", null, "mochitest", "mochiuser1", "mochipass1", "", ""],
["http://mochi.test:8888", null, "mochitest2", "mochiuser2", "mochipass2", "", ""],
["http://mochi.test:8888", null, "mochitest3", "mochiuser3", "mochipass3-old", "", ""],
// Logins to test scheme upgrades (allowed) and downgrades (disallowed)
["http://example.com", null, "schemeUpgrade", "httpUser", "httpPass", "", ""],
["https://example.com", null, "schemeDowngrade", "httpsUser", "httpsPass", "", ""],
// HTTP and HTTPS version of the same domain and realm but with different passwords.
["http://example.org", null, "schemeUpgradeDedupe", "dedupeUser", "httpPass", "", ""],
["https://example.org", null, "schemeUpgradeDedupe", "dedupeUser", "httpsPass", "", ""]
);
runInParent(() => {
let login3A, login3B, login4;
login3A = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login3B = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login4 = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let httpUpgradeLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let httpsDowngradeLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let dedupeHttpUpgradeLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let dedupeHttpsUpgradeLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login3A.init("http://mochi.test:8888", null, "mochitest",
"mochiuser1", "mochipass1", "", "");
login3B.init("http://mochi.test:8888", null, "mochitest2",
"mochiuser2", "mochipass2", "", "");
login4.init("http://mochi.test:8888", null, "mochitest3",
"mochiuser3", "mochipass3-old", "", "");
// Logins to test scheme upgrades (allowed) and downgrades (disallowed)
httpUpgradeLogin.init("http://example.com", null, "schemeUpgrade",
"httpUser", "httpPass", "", "");
httpsDowngradeLogin.init("https://example.com", null, "schemeDowngrade",
"httpsUser", "httpsPass", "", "");
// HTTP and HTTPS version of the same domain and realm but with different passwords.
dedupeHttpUpgradeLogin.init("http://example.org", null, "schemeUpgradeDedupe",
"dedupeUser", "httpPass", "", "");
dedupeHttpsUpgradeLogin.init("https://example.org", null, "schemeUpgradeDedupe",
"dedupeUser", "httpsPass", "", "");
Services.logins.addLogin(login3A);
Services.logins.addLogin(login3B);
Services.logins.addLogin(login4);
Services.logins.addLogin(httpUpgradeLogin);
Services.logins.addLogin(httpsDowngradeLogin);
Services.logins.addLogin(dedupeHttpUpgradeLogin);
Services.logins.addLogin(dedupeHttpsUpgradeLogin);
});
add_task(async function test_iframe() {
@ -251,7 +282,7 @@ add_task(async function test_schemeUpgrade() {
});
add_task(async function test_schemeDowngrade() {
const state = {
let state = {
msg: "This site is asking you to sign in. Warning: Your login information " +
"will be shared with example.com, not the website you are currently visiting.",
title: "Authentication Required",
@ -267,14 +298,14 @@ add_task(async function test_schemeDowngrade() {
focused: "textField",
defButton: "button0",
};
const action = {
let action = {
buttonClick: "cancel",
};
const promptDone = handlePrompt(state, action);
let promptDone = handlePrompt(state, action);
// The following tests are driven by iframe loads
const iframeLoaded = onloadPromiseFor("iframe");
let iframeLoaded = onloadPromiseFor("iframe");
iframe.src = "http://example.com" + AUTHENTICATE_PATH +
"?user=unused&pass=unused&realm=schemeDowngrade";
await promptDone;
@ -282,7 +313,7 @@ add_task(async function test_schemeDowngrade() {
});
add_task(async function test_schemeUpgrade_dedupe() {
const state = {
let state = {
msg: "This site is asking you to sign in. Warning: Your login information " +
"will be shared with example.org, not the website you are currently visiting.",
title: "Authentication Required",
@ -298,14 +329,14 @@ add_task(async function test_schemeUpgrade_dedupe() {
focused: "textField",
defButton: "button0",
};
const action = {
let action = {
buttonClick: "ok",
};
const promptDone = handlePrompt(state, action);
let promptDone = handlePrompt(state, action);
// The following tests are driven by iframe loads
const iframeLoaded = onloadPromiseFor("iframe");
let iframeLoaded = onloadPromiseFor("iframe");
iframe.src = "https://example.org" + AUTHENTICATE_PATH +
"?user=dedupeUser&pass=httpsPass&realm=schemeUpgradeDedupe";
await promptDone;

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

@ -21,13 +21,21 @@
modalType = authPromptModalType;
add_setup(async () => {
await addLoginsInParent(
["http://mochi.test:8888", null, "mochitest", "mochiuser1", "mochipass1", "", ""]
);
let loginAddedPromise = promiseStorageChanged(["addLogin"]);
runInParent(() => {
let login = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login.init("http://mochi.test:8888", null, "mochitest",
"mochiuser1", "mochipass1", "", "");
Services.logins.addLogin(login);
});
await loginAddedPromise;
});
add_task(async function test_sandbox_xhr() {
const state = {
let state = {
msg: "This site is asking you to sign in.",
title: "Authentication Required",
textValue: "mochiuser1",
@ -42,21 +50,21 @@ add_task(async function test_sandbox_xhr() {
focused: "textField",
defButton: "button0",
};
const action = {
let action = {
buttonClick: "ok",
};
const promptDone = handlePrompt(state, action);
let promptDone = handlePrompt(state, action);
const url = new URL("authenticate.sjs?user=mochiuser1&pass=mochipass1", window.location.href);
const sandboxConstructor = SpecialPowers.Cu.Sandbox;
const sandbox = new sandboxConstructor(this, {wantXrays: true});
let url = new URL("authenticate.sjs?user=mochiuser1&pass=mochipass1", window.location.href);
let sandboxConstructor = SpecialPowers.Cu.Sandbox;
let sandbox = new sandboxConstructor(this, {wantXrays: true});
function sandboxedRequest(sandboxedUrl) {
const req = new XMLHttpRequest();
let req = new XMLHttpRequest();
req.open("GET", sandboxedUrl, true);
req.send(null);
}
const loginModifiedPromise = promiseStorageChanged(["modifyLogin"]);
let loginModifiedPromise = promiseStorageChanged(["modifyLogin"]);
sandbox.sandboxedRequest = sandboxedRequest(url);
info("send the XHR request in the sandbox");
SpecialPowers.Cu.evalInSandbox("sandboxedRequest;", sandbox);

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

@ -16,8 +16,11 @@
<pre id="test">
<script class="testbody" type="text/javascript">
const level = Ci.nsIAuthPrompt2.LEVEL_NONE;
const authinfo = {
var state, action;
var isOk;
var level = Ci.nsIAuthPrompt2.LEVEL_NONE;
var authinfo = {
username: "",
password: "",
domain: "",
@ -30,15 +33,15 @@ const authinfo = {
// Let prompt_common know what kind of modal type is enabled for auth prompts.
modalType = authPromptModalType;
const prompterParent = runInParent(() => {
let prompterParent = runInParent(() => {
const promptFac = Cc["@mozilla.org/passwordmanager/authpromptfactory;1"].
getService(Ci.nsIPromptFactory);
const chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
const prompter2 = promptFac.getPrompt(chromeWin, Ci.nsIAuthPrompt2);
let chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
let prompter2 = promptFac.getPrompt(chromeWin, Ci.nsIAuthPrompt2);
prompter2.QueryInterface(Ci.nsILoginManagerAuthPrompter).browser = chromeWin.gBrowser.selectedBrowser;
const channels = {};
let channels = {};
channels.channel1 = Services.io.newChannel("http://example.com",
null,
null,
@ -60,35 +63,58 @@ const prompterParent = runInParent(() => {
Ci.nsIContentPolicy.TYPE_OTHER);
addMessageListener("proxyPrompter", function onMessage(msg) {
const args = [...msg.args];
const channelName = args.shift();
let args = [...msg.args];
let channelName = args.shift();
// Replace the channel name string (arg. 0) with the channel by that name.
args.unshift(channels[channelName]);
const rv = prompter2[msg.methodName](...args);
let rv = prompter2[msg.methodName](...args);
return {
rv,
// Send the args back to content so out/inout args can be checked.
args: msg.args,
};
});
let login1, login2A, login2B, login2C, login2D, login2E;
login1 = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login2A = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login2B = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login2C = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login2D = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login2E = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login1.init("http://example.com", null, "http://example.com",
"", "examplepass", "", "");
login2A.init("http://example2.com", null, "http://example2.com",
"user1name", "user1pass", "", "");
login2B.init("http://example2.com", null, "http://example2.com",
"user2name", "user2pass", "", "");
login2C.init("http://example2.com", null, "http://example2.com",
"user3.name@host", "user3pass", "", "");
login2D.init("http://example2.com", null, "http://example2.com",
"100@beef", "user3pass", "", "");
login2E.init("http://example2.com", null, "http://example2.com",
"100%beef", "user3pass", "", "");
Services.logins.addLogin(login1);
Services.logins.addLogin(login2A);
Services.logins.addLogin(login2B);
Services.logins.addLogin(login2C);
Services.logins.addLogin(login2D);
Services.logins.addLogin(login2E);
});
const prompter2 = new PrompterProxy(prompterParent);
add_setup(async () => {
await addLoginsInParent(
["http://example.com", null, "http://example.com", "", "examplepass", "", ""],
["http://example2.com", null, "http://example2.com", "user1name", "user1pass", "", ""],
["http://example2.com", null, "http://example2.com", "user2name", "user2pass", "", ""],
["http://example2.com", null, "http://example2.com", "user3.name@host", "user3pass", "", ""],
["http://example2.com", null, "http://example2.com", "100@beef", "user3pass", "", ""],
["http://example2.com", null, "http://example2.com", "100%beef", "user3pass", "", ""]
);
});
let prompter2 = new PrompterProxy(prompterParent);
add_task(async function test_accept() {
const state = {
state = {
msg: "This site is asking you to sign in.",
title: "Authentication Required",
textValue: "inuser",
@ -103,7 +129,7 @@ add_task(async function test_accept() {
focused: "textField",
defButton: "button0",
};
const action = {
action = {
buttonClick: "ok",
textField: "outuser",
passField: "outpass",
@ -116,7 +142,7 @@ add_task(async function test_accept() {
// Since prompter2 is actually a proxy to send a message to a chrome script and
// we can't send a channel in a message, we instead send the channel name that
// already exists in the chromeScript.
const isOk = prompter2.promptAuth("channel1", level, authinfo);
isOk = prompter2.promptAuth("channel1", level, authinfo);
await promptDone;
ok(isOk, "Checking dialog return value (accept)");
@ -125,7 +151,7 @@ add_task(async function test_accept() {
});
add_task(async function test_cancel() {
const state = {
state = {
msg: "This site is asking you to sign in.",
title: "Authentication Required",
textValue: "outuser",
@ -140,11 +166,11 @@ add_task(async function test_cancel() {
focused: "textField",
defButton: "button0",
};
const action = {
action = {
buttonClick: "cancel",
};
promptDone = handlePrompt(state, action);
const isOk = prompter2.promptAuth("channel1", level, authinfo);
isOk = prompter2.promptAuth("channel1", level, authinfo);
await promptDone;
ok(!isOk, "Checking dialog return value (cancel)");
@ -152,7 +178,7 @@ add_task(async function test_cancel() {
add_task(async function test_pwonly() {
// test filling in password-only login
const state = {
state = {
msg: "This site is asking you to sign in.",
title: "Authentication Required",
textValue: "",
@ -167,7 +193,7 @@ add_task(async function test_pwonly() {
focused: "textField",
defButton: "button0",
};
const action = {
action = {
buttonClick: "ok",
};
authinfo.username = "";
@ -175,7 +201,7 @@ add_task(async function test_pwonly() {
authinfo.realm = "http://example.com";
promptDone = handlePrompt(state, action);
const isOk = prompter2.promptAuth("channel1", level, authinfo);
isOk = prompter2.promptAuth("channel1", level, authinfo);
await promptDone;
ok(isOk, "Checking dialog return value (accept)");
@ -186,7 +212,7 @@ add_task(async function test_pwonly() {
add_task(async function test_multipleExisting() {
// test filling in existing login (undetermined from multiple selection)
// user2name/user2pass would also be valid to fill here.
const state = {
state = {
msg: "This site is asking you to sign in.",
title: "Authentication Required",
textValue: "user1name",
@ -201,7 +227,7 @@ add_task(async function test_multipleExisting() {
focused: "textField",
defButton: "button0",
};
const action = {
action = {
buttonClick: "ok",
};
authinfo.username = "";
@ -209,7 +235,7 @@ add_task(async function test_multipleExisting() {
authinfo.realm = "http://example2.com";
promptDone = handlePrompt(state, action);
const isOk = prompter2.promptAuth("channel2", level, authinfo);
isOk = prompter2.promptAuth("channel2", level, authinfo);
await promptDone;
ok(isOk, "Checking dialog return value (accept)");
@ -220,7 +246,7 @@ add_task(async function test_multipleExisting() {
add_task(async function test_multipleExisting2() {
// test filling in existing login (undetermined --> user1)
// user2name/user2pass would also be valid to fill here.
const state = {
state = {
msg: "This site is asking you to sign in.",
title: "Authentication Required",
textValue: "user1name",
@ -236,7 +262,7 @@ add_task(async function test_multipleExisting2() {
defButton: "button0",
};
// enter one of the known logins, test 504+505 exercise the two possible states.
const action = {
action = {
buttonClick: "ok",
textField: "user1name",
passField: "user1pass",
@ -246,7 +272,7 @@ add_task(async function test_multipleExisting2() {
authinfo.realm = "http://example2.com";
promptDone = handlePrompt(state, action);
const isOk = prompter2.promptAuth("channel2", level, authinfo);
isOk = prompter2.promptAuth("channel2", level, authinfo);
await promptDone;
ok(isOk, "Checking dialog return value (accept)");
@ -257,7 +283,7 @@ add_task(async function test_multipleExisting2() {
add_task(async function test_multipleExisting3() {
// test filling in existing login (undetermined --> user2)
// user2name/user2pass would also be valid to fill here.
const state = {
state = {
msg: "This site is asking you to sign in.",
title: "Authentication Required",
textValue: "user1name",
@ -273,7 +299,7 @@ add_task(async function test_multipleExisting3() {
defButton: "button0",
};
// enter one of the known logins, test 504+505 exercise the two possible states.
const action = {
action = {
buttonClick: "ok",
textField: "user2name",
passField: "user2pass",
@ -283,7 +309,7 @@ add_task(async function test_multipleExisting3() {
authinfo.realm = "http://example2.com";
promptDone = handlePrompt(state, action);
const isOk = prompter2.promptAuth("channel2", level, authinfo);
isOk = prompter2.promptAuth("channel2", level, authinfo);
await promptDone;
ok(isOk, "Checking dialog return value (accept)");
@ -294,7 +320,7 @@ add_task(async function test_multipleExisting3() {
add_task(async function test_changingMultiple() {
// test changing a password (undetermined --> user2 w/ newpass)
// user2name/user2pass would also be valid to fill here.
const state = {
state = {
msg: "This site is asking you to sign in.",
title: "Authentication Required",
textValue: "user1name",
@ -310,7 +336,7 @@ add_task(async function test_changingMultiple() {
defButton: "button0",
};
// force to user2, and change the password
const action = {
action = {
buttonClick: "ok",
textField: "user2name",
passField: "NEWuser2pass",
@ -320,7 +346,7 @@ add_task(async function test_changingMultiple() {
authinfo.realm = "http://example2.com";
promptDone = handlePrompt(state, action);
const isOk = prompter2.promptAuth("channel2", level, authinfo);
isOk = prompter2.promptAuth("channel2", level, authinfo);
await promptDone;
ok(isOk, "Checking dialog return value (accept)");
@ -331,7 +357,7 @@ add_task(async function test_changingMultiple() {
add_task(async function test_changingMultiple2() {
// test changing a password (undetermined --> user2 w/ origpass)
// user2name/user2pass would also be valid to fill here.
const state = {
state = {
msg: "This site is asking you to sign in.",
title: "Authentication Required",
textValue: "user1name",
@ -347,7 +373,7 @@ add_task(async function test_changingMultiple2() {
defButton: "button0",
};
// force to user2, and change the password back
const action = {
action = {
buttonClick: "ok",
textField: "user2name",
passField: "user2pass",
@ -357,7 +383,7 @@ add_task(async function test_changingMultiple2() {
authinfo.realm = "http://example2.com";
promptDone = handlePrompt(state, action);
const isOk = prompter2.promptAuth("channel2", level, authinfo);
isOk = prompter2.promptAuth("channel2", level, authinfo);
await promptDone;
ok(isOk, "Checking dialog return value (accept)");

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

@ -92,7 +92,7 @@ let chromeScript = runInParent(() => {
onStopRequest(request, status) {}
}
async function initLogins(pi) {
function initLogins(pi) {
mozproxyURL = `moz-proxy://${pi.host}:${pi.port}`;
let proxyLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(
@ -109,7 +109,7 @@ let chromeScript = runInParent(() => {
""
);
await Services.logins.addLoginAsync(proxyLogin);
Services.logins.addLogin(proxyLogin);
}
let resolveCallback = {
@ -126,8 +126,8 @@ let chromeScript = runInParent(() => {
return this;
},
async onProxyAvailable(req, uri, pi, status) {
await initLogins(pi);
onProxyAvailable(req, uri, pi, status) {
initLogins(pi);
// I'm cheating a bit here... We should probably do some magic foo to get
// something implementing nsIProxiedProtocolHandler and then call

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

@ -11,154 +11,199 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script>
let readyPromise = registerRunTests(5);
let chromeScript = runInParent(function chromeSetup() {
let login1A = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let login2A = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let login2B = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login1A.init("http://mochi.test:8888", "http://username-focus-1", null,
"testuser1A", "testpass1A", "", "");
login2A.init("http://mochi.test:8888", "http://username-focus-2", null,
"testuser2A", "testpass2A", "", "");
login2B.init("http://mochi.test:8888", "http://username-focus-2", null,
"testuser2B", "testpass2B", "", "");
Services.logins.addLogin(login1A);
Services.logins.addLogin(login2A);
Services.logins.addLogin(login2B);
});
</script>
<p id="display"></p>
<div id="content"></div>
<div id="content">
<!-- first 3 forms have a matching user+pass login -->
<!-- user+pass form. -->
<form id="form-autofilled" action="http://username-focus-1">
<input type="text" name="uname">
<input type="password" name="pword">
<button type="submit" name="submit">Submit</button>
</form>
<!-- user+pass form, username prefilled -->
<form id="form-autofilled-prefilled-un" action="http://username-focus-1">
<input type="text" name="uname" value="testuser1A">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
<!-- user+pass form. -->
<form id="form-autofilled-focused-dynamic" action="http://username-focus-1">
<input type="text" name="uname">
<input type="not-yet-password" name="pword">
<button type="submit">Submit</button>
</form>
<!-- next 5 forms have matching user+pass (2x) logins -->
<!-- user+pass form. -->
<form id="form-multiple" action="http://username-focus-2">
<input type="text" name="uname">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
<!-- user+pass form dynamic with existing focus -->
<form id="form-multiple-dynamic" action="http://username-focus-2">
<input type="text" name="uname">
<input type="not-yet-password" name="pword">
<button type="submit">Submit</button>
</form>
<!-- user+pass form, username prefilled -->
<form id="form-multiple-prefilled-un1" action="http://username-focus-2">
<input type="text" name="uname" value="testuser2A">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
<!-- user+pass form, different username prefilled -->
<form id="form-multiple-prefilled-un2" action="http://username-focus-2">
<input type="text" name="uname" value="testuser2B">
<input type="password" name="pword">
<button type="submit">Submit</button>
</form>
<!-- user+pass form, username prefilled with existing focus -->
<form id="form-multiple-prefilled-focused-dynamic" action="http://username-focus-2">
<input type="text" name="uname" value="testuser2B">
<input type="not-yet-password" name="pword">
<button type="submit">Submit</button>
</form>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
const action1 = "http://username-focus-1";
const action2 = "http://username-focus-2";
function removeFocus() {
getFormElementByName("-autofilled", "submit").focus();
}
add_setup(async () => {
await addLoginsInParent(
[location.origin, action1, null, "testuser1A", "testpass1A", "", ""],
[location.origin, action2, null, "testuser2A", "testpass2A", "", ""],
[location.origin, action2, null, "testuser2B", "testpass2B", "", ""]
);
ok(readyPromise, "check promise is available");
await readyPromise;
});
add_task(async function autofilled() {
const form = createLoginForm({ action: action1 });
add_task(async function test_autofilled() {
let usernameField = getFormElementByName("-autofilled", "uname");
info("Username and password already filled so don't show autocomplete");
await noPopupBy(() => form.uname.focus());
await noPopupBy(() => usernameField.focus());
form.submit.focus();
form.uname.value = "testuser";
removeFocus();
usernameField.value = "testuser";
info("Focus when we don't have an exact match");
await popupBy(() => form.uname.focus());
await popupBy(() => usernameField.focus());
});
add_task(async function autofilled_prefilled_un() {
const form = createLoginForm({
action: action1,
username: {
value: "testuser1A"
}
});
add_task(async function test_autofilled_prefilled_un() {
let usernameField = getFormElementByName("-autofilled-prefilled-un", "uname");
info("Username and password already filled so don't show autocomplete");
await noPopupBy(() => form.uname.focus());
await noPopupBy(() => usernameField.focus());
form.submit.focus();
form.uname.value = "testuser";
removeFocus();
usernameField.value = "testuser";
info("Focus when we don't have an exact match");
await popupBy(() => form.uname.focus());
await popupBy(() => usernameField.focus());
});
add_task(async function autofilled_focused_dynamic() {
const form = createLoginForm({
action: action1,
password: {
type: "not-yet-password"
}
});
add_task(async function test_autofilled_focused_dynamic() {
let usernameField = getFormElementByName("-autofilled-focused-dynamic", "uname");
let passwordField = getFormElementByName("-autofilled-focused-dynamic", "pword");
info("Username and password will be filled while username focused");
await noPopupBy(() => form.uname.focus());
await noPopupBy(() => usernameField.focus());
info("triggering autofill");
await noPopupBy(() => form.pword.type = "password");
const popupState = await getPopupState();
is(popupState.open, false, "Check popup is closed");
form.submit.focus();
form.pword.value = "test";
info("Focus when we don't have an exact match");
await popupBy(() => form.uname.focus());
});
// Begin testing forms that have multiple saved logins
add_task(async function multiple() {
const form = createLoginForm({ action: action2 });
info("Fields not filled due to multiple so autocomplete upon focus");
await popupBy(() => form.uname.focus());
});
add_task(async function multiple_dynamic() {
const form = createLoginForm({
action: action2,
password: {
type: "not-yet-password"
}
});
info("Fields not filled but username is focused upon marking so open");
await noPopupBy(() => form.uname.focus());
info("triggering _fillForm code");
await popupBy(() => form.pword.type = "password");
});
add_task(async function multiple_prefilled_un1() {
const form = createLoginForm({
action: action2,
username: {
value: "testuser2A"
}
});
info("Username and password already filled so don't show autocomplete");
await noPopupBy(() => form.uname.focus());
form.submit.focus();
form.uname.value = "testuser";
info("Focus when we don't have an exact match");
await popupBy(() => form.uname.focus());
});
add_task(async function multiple_prefilled_un2() {
const form = createLoginForm({
action: action2,
username: {
value: "testuser2B"
}
});
info("Username and password already filled so don't show autocomplete");
await noPopupBy(() => form.uname.focus());
form.submit.focus();
form.uname.value = "testuser";
info("Focus when we don't have an exact match");
await popupBy(() => form.uname.focus());
});
add_task(async function multiple_prefilled_focused_dynamic() {
const form = createLoginForm({
action: action2,
username: {
value: "testuser2B"
},
password: {
type: "not-yet-password"
}
});
info("Username and password will be filled while username focused");
await noPopupBy(() => form.uname.focus());
info("triggering autofill");
await noPopupBy(() => form.pword.type = "password");
await noPopupBy(() => passwordField.type = "password");
let popupState = await getPopupState();
is(popupState.open, false, "Check popup is closed");
form.submit.focus();
form.pword.value = "test";
removeFocus();
passwordField.value = "test";
info("Focus when we don't have an exact match");
await popupBy(() => form.uname.focus());
await popupBy(() => usernameField.focus());
});
// Begin testing forms that have multiple saved logins
add_task(async function test_multiple() {
let usernameField = getFormElementByName("-multiple", "uname");
info("Fields not filled due to multiple so autocomplete upon focus");
await popupBy(() => usernameField.focus());
});
add_task(async function test_multiple_dynamic() {
let usernameField = getFormElementByName("-multiple-dynamic", "uname");
let passwordField = getFormElementByName("-multiple-dynamic", "pword");
info("Fields not filled but username is focused upon marking so open");
await noPopupBy(() => usernameField.focus());
info("triggering _fillForm code");
await popupBy(() => passwordField.type = "password");
});
add_task(async function test_multiple_prefilled_un1() {
let usernameField = getFormElementByName("-multiple-prefilled-un1", "uname");
info("Username and password already filled so don't show autocomplete");
await noPopupBy(() => usernameField.focus());
removeFocus();
usernameField.value = "testuser";
info("Focus when we don't have an exact match");
await popupBy(() => usernameField.focus());
});
add_task(async function test_multiple_prefilled_un2() {
let usernameField = getFormElementByName("-multiple-prefilled-un2", "uname");
info("Username and password already filled so don't show autocomplete");
await noPopupBy(() => usernameField.focus());
removeFocus();
usernameField.value = "testuser";
info("Focus when we don't have an exact match");
await popupBy(() => usernameField.focus());
});
add_task(async function test_multiple_prefilled_focused_dynamic() {
let usernameField = getFormElementByName("-multiple-prefilled-focused-dynamic", "uname");
let passwordField = getFormElementByName("-multiple-prefilled-focused-dynamic", "pword");
info("Username and password will be filled while username focused");
await noPopupBy(() => usernameField.focus());
info("triggering autofill");
await noPopupBy(() => passwordField.type = "password");
let popupState = await getPopupState();
is(popupState.open, false, "Check popup is closed");
removeFocus();
passwordField.value = "test";
info("Focus when we don't have an exact match");
await popupBy(() => usernameField.focus());
});
</script>
</pre>

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

@ -62,11 +62,22 @@ let prompterParent = runInParent(() => {
let prompter1 = new PrompterProxy(prompterParent);
add_setup(async () => {
await addLoginsInParent(
["http://mochi.test:8888", null, "xhr", "xhruser1", "xhrpass1"],
["http://mochi.test:8888", null, "xhr2", "xhruser2", "xhrpass2"]
);
add_task(function setup() {
runInParent(function initLogins() {
let nsLoginInfo = Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
Ci.nsILoginInfo, "init");
let login1 = new nsLoginInfo("http://mochi.test:8888", null, "xhr",
"xhruser1", "xhrpass1");
let login2 = new nsLoginInfo("http://mochi.test:8888", null, "xhr2",
"xhruser2", "xhrpass2");
try {
Services.logins.addLogin(login1);
Services.logins.addLogin(login2);
} catch (e) {
assert.ok(false, "addLogin threw: " + e);
}
});
});
add_task(async function test1() {

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

@ -1,4 +1,4 @@
const { LoginManagerPrompter } = ChromeUtils.importESModule(
let { LoginManagerPrompter } = ChromeUtils.importESModule(
"resource://gre/modules/LoginManagerPrompter.sys.mjs"
);
@ -110,27 +110,28 @@ function _setPrefs() {
});
}
async function _saveLogins(loginDatas) {
const logins = loginDatas.map(loginData => {
let login;
if (loginData.isAuth) {
login = TestData.authLogin({
origin: loginData.origin ?? "https://example.com",
httpRealm: "example-realm",
username: loginData.username,
password: loginData.password,
});
} else {
login = TestData.formLogin({
origin: loginData.origin ?? "https://example.com",
formActionOrigin: "https://example.com",
username: loginData.username,
password: loginData.password,
});
}
return login;
});
await Services.logins.addLogins(logins);
function _saveLogins(logins) {
logins
.map(loginData => {
let login;
if (loginData.isAuth) {
login = TestData.authLogin({
origin: loginData.origin ?? "https://example.com",
httpRealm: "example-realm",
username: loginData.username,
password: loginData.password,
});
} else {
login = TestData.formLogin({
origin: loginData.origin ?? "https://example.com",
formActionOrigin: "https://example.com",
username: loginData.username,
password: loginData.password,
});
}
return login;
})
.forEach(login => Services.logins.addLogin(login));
}
function _compare(expectedArr, actualArr) {
@ -141,8 +142,8 @@ function _compare(expectedArr, actualArr) {
"Expect expectedArr and actualArr to be the same length"
);
for (let i = 0; i < expectedArr.length; i++) {
const expected = expectedArr[i];
const actual = actualArr[i];
let expected = expectedArr[i];
let actual = actualArr[i];
Assert.ok(
expected.text == actual.text,
@ -158,7 +159,7 @@ function _compare(expectedArr, actualArr) {
async function _test(testCase) {
info(`Starting test case: ${testCase.description}`);
info(`Storing saved logins: ${JSON.stringify(testCase.savedLogins)}`);
await _saveLogins(testCase.savedLogins);
_saveLogins(testCase.savedLogins);
if (!testCase.isLoggedIn) {
// Primary Password should be enabled and locked
@ -166,7 +167,7 @@ async function _test(testCase) {
}
info("Computing results");
const result = await LoginManagerPrompter._getUsernameSuggestions(
let result = await LoginManagerPrompter._getUsernameSuggestions(
LOGIN,
testCase.possibleUsernames
);
@ -182,7 +183,7 @@ async function _test(testCase) {
add_task(async function test_LoginManagerPrompter_getUsernameSuggestions() {
_setPrefs();
for (const tc of TEST_CASES) {
for (let tc of TEST_CASES) {
await _test(tc);
}
});

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

@ -252,7 +252,9 @@ function authLogin(modifications = {}) {
async function runTestcase({ formOrigin, savedLogins, expectedItems }) {
const DOCUMENT_CONTENT = "<form><input id='pw' type=password></form>";
await Services.logins.addLogins(savedLogins);
for (let login of savedLogins) {
Services.logins.addLogin(login);
}
// Create the logins menuitems fragment.
let { fragment, document } = createLoginsFragment(

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

@ -41,27 +41,24 @@
* Adds a login with an empty formActionOrigin, then it verifies that no other
* form logins can be added for the same host.
*/
add_task(async function test_addLogin_wildcard() {
add_task(function test_addLogin_wildcard() {
let loginInfo = TestData.formLogin({
origin: "http://any.example.com",
formActionOrigin: "",
});
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
// Normal form logins cannot be added anymore.
loginInfo = TestData.formLogin({ origin: "http://any.example.com" });
await Assert.rejects(
Services.logins.addLoginAsync(loginInfo),
/already exists/
);
Assert.throws(() => Services.logins.addLogin(loginInfo), /already exists/);
// Authentication logins can still be added.
loginInfo = TestData.authLogin({ origin: "http://any.example.com" });
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
// Form logins can be added for other hosts.
loginInfo = TestData.formLogin({ origin: "http://other.example.com" });
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
});
/**

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

@ -16,27 +16,27 @@
/**
* Tests legacy validation with addLogin.
*/
add_task(async function test_addLogin_invalid_characters_legacy() {
add_task(function test_addLogin_invalid_characters_legacy() {
// Test newlines and carriage returns in properties that contain URLs.
for (let testValue of [
"http://newline\n.example.com",
"http://carriagereturn.example.com\r",
]) {
let loginInfo = TestData.formLogin({ origin: testValue });
await Assert.rejects(
Services.logins.addLoginAsync(loginInfo),
Assert.throws(
() => Services.logins.addLogin(loginInfo),
/login values can't contain newlines/
);
loginInfo = TestData.formLogin({ formActionOrigin: testValue });
await Assert.rejects(
Services.logins.addLoginAsync(loginInfo),
Assert.throws(
() => Services.logins.addLogin(loginInfo),
/login values can't contain newlines/
);
loginInfo = TestData.authLogin({ httpRealm: testValue });
await Assert.rejects(
Services.logins.addLoginAsync(loginInfo),
Assert.throws(
() => Services.logins.addLogin(loginInfo),
/login values can't contain newlines/
);
}
@ -44,35 +44,35 @@ add_task(async function test_addLogin_invalid_characters_legacy() {
// Test newlines and carriage returns in form field names.
for (let testValue of ["newline_field\n", "carriagereturn\r_field"]) {
let loginInfo = TestData.formLogin({ usernameField: testValue });
await Assert.rejects(
Services.logins.addLoginAsync(loginInfo),
Assert.throws(
() => Services.logins.addLogin(loginInfo),
/login values can't contain newlines/
);
loginInfo = TestData.formLogin({ passwordField: testValue });
await Assert.rejects(
Services.logins.addLoginAsync(loginInfo),
Assert.throws(
() => Services.logins.addLogin(loginInfo),
/login values can't contain newlines/
);
}
// Test a single dot as the value of usernameField and formActionOrigin.
let loginInfo = TestData.formLogin({ usernameField: "." });
await Assert.rejects(
Services.logins.addLoginAsync(loginInfo),
Assert.throws(
() => Services.logins.addLogin(loginInfo),
/login values can't be periods/
);
loginInfo = TestData.formLogin({ formActionOrigin: "." });
await Assert.rejects(
Services.logins.addLoginAsync(loginInfo),
Assert.throws(
() => Services.logins.addLogin(loginInfo),
/login values can't be periods/
);
// Test the sequence " (" inside the value of the "origin" property.
loginInfo = TestData.formLogin({ origin: "http://parens (.example.com" });
await Assert.rejects(
Services.logins.addLoginAsync(loginInfo),
Assert.throws(
() => Services.logins.addLogin(loginInfo),
/bad parens in origin/
);
});

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

@ -23,17 +23,14 @@ const MAX_DATE_MS = 8640000000000000;
* This argument is passed to the "Assert.throws" test to determine which
* error is expected from the modification functions.
*/
async function checkLoginInvalid(aLoginInfo, aExpectedError) {
function checkLoginInvalid(aLoginInfo, aExpectedError) {
// Try to add the new login, and verify that no data is stored.
await Assert.rejects(
Services.logins.addLoginAsync(aLoginInfo),
aExpectedError
);
Assert.throws(() => Services.logins.addLogin(aLoginInfo), aExpectedError);
LoginTestUtils.checkLogins([]);
// Add a login for the modification tests.
let testLogin = TestData.formLogin({ origin: "http://modify.example.com" });
await Services.logins.addLoginAsync(testLogin);
Services.logins.addLogin(testLogin);
// Try to modify the existing login using nsILoginInfo and nsIPropertyBag.
Assert.throws(
@ -90,17 +87,16 @@ function compareAttributes(objectA, objectB, attributes) {
/**
* Tests that adding logins to the database works.
*/
add_task(async function test_addLogin_removeLogin() {
add_task(function test_addLogin_removeLogin() {
// Each login from the test data should be valid and added to the list.
await Services.logins.addLogins(TestData.loginList());
for (let loginInfo of TestData.loginList()) {
Services.logins.addLogin(loginInfo);
}
LoginTestUtils.checkLogins(TestData.loginList());
// Trying to add each login again should result in an error.
for (let loginInfo of TestData.loginList()) {
await Assert.rejects(
Services.logins.addLoginAsync(loginInfo),
/This login already exists./
);
Assert.throws(() => Services.logins.addLogin(loginInfo), /already exists/);
}
// Removing each login should succeed.
@ -187,70 +183,64 @@ add_task(async function event_data_includes_plaintext_username_and_password() {
* The legacy case of an empty string in formActionOrigin and a null value in
* httpRealm is also supported for storage at the moment.
*/
add_task(async function test_invalid_httpRealm_formActionOrigin() {
add_task(function test_invalid_httpRealm_formActionOrigin() {
// httpRealm === null, formActionOrigin === null
await checkLoginInvalid(
checkLoginInvalid(
TestData.formLogin({ formActionOrigin: null }),
/without a httpRealm or formActionOrigin/
);
// httpRealm === "", formActionOrigin === null
await checkLoginInvalid(
checkLoginInvalid(
TestData.authLogin({ httpRealm: "" }),
/without a httpRealm or formActionOrigin/
);
// httpRealm === null, formActionOrigin === ""
// TODO: This is not enforced for now.
// await checkLoginInvalid(TestData.formLogin({ formActionOrigin: "" }),
// checkLoginInvalid(TestData.formLogin({ formActionOrigin: "" }),
// /without a httpRealm or formActionOrigin/);
// httpRealm === "", formActionOrigin === ""
let login = TestData.formLogin({ formActionOrigin: "" });
login.httpRealm = "";
await checkLoginInvalid(login, /both a httpRealm and formActionOrigin/);
checkLoginInvalid(login, /both a httpRealm and formActionOrigin/);
// !!httpRealm, !!formActionOrigin
login = TestData.formLogin();
login.httpRealm = "The HTTP Realm";
await checkLoginInvalid(login, /both a httpRealm and formActionOrigin/);
checkLoginInvalid(login, /both a httpRealm and formActionOrigin/);
// httpRealm === "", !!formActionOrigin
login = TestData.formLogin();
login.httpRealm = "";
await checkLoginInvalid(login, /both a httpRealm and formActionOrigin/);
checkLoginInvalid(login, /both a httpRealm and formActionOrigin/);
// !!httpRealm, formActionOrigin === ""
login = TestData.authLogin();
login.formActionOrigin = "";
await checkLoginInvalid(login, /both a httpRealm and formActionOrigin/);
checkLoginInvalid(login, /both a httpRealm and formActionOrigin/);
});
/**
* Tests null or empty values in required login properties.
*/
add_task(async function test_missing_properties() {
await checkLoginInvalid(
add_task(function test_missing_properties() {
checkLoginInvalid(
TestData.formLogin({ origin: null }),
/null or empty origin/
);
await checkLoginInvalid(
TestData.formLogin({ origin: "" }),
/null or empty origin/
);
checkLoginInvalid(TestData.formLogin({ origin: "" }), /null or empty origin/);
await checkLoginInvalid(
TestData.formLogin({ username: null }),
/null username/
);
checkLoginInvalid(TestData.formLogin({ username: null }), /null username/);
await checkLoginInvalid(
checkLoginInvalid(
TestData.formLogin({ password: null }),
/null or empty password/
);
await checkLoginInvalid(
checkLoginInvalid(
TestData.formLogin({ password: "" }),
/null or empty password/
);
@ -259,7 +249,7 @@ add_task(async function test_missing_properties() {
/**
* Tests invalid NUL characters in nsILoginInfo properties.
*/
add_task(async function test_invalid_characters() {
add_task(function test_invalid_characters() {
let loginList = [
TestData.authLogin({ origin: "http://null\0X.example.com" }),
TestData.authLogin({ httpRealm: "realm\0" }),
@ -271,7 +261,7 @@ add_task(async function test_invalid_characters() {
TestData.formLogin({ password: "pass\0word" }),
];
for (let loginInfo of loginList) {
await checkLoginInvalid(loginInfo, /login values can't contain nulls/);
checkLoginInvalid(loginInfo, /login values can't contain nulls/);
}
});
@ -288,9 +278,10 @@ add_task(function test_removeLogin_nonexisting() {
/**
* Tests removing all logins at once.
*/
add_task(async function test_removeAllUserFacingLogins() {
await Services.logins.addLogins(TestData.loginList());
add_task(function test_removeAllUserFacingLogins() {
for (let loginInfo of TestData.loginList()) {
Services.logins.addLogin(loginInfo);
}
Services.logins.removeAllUserFacingLogins();
LoginTestUtils.checkLogins([]);
@ -301,7 +292,7 @@ add_task(async function test_removeAllUserFacingLogins() {
/**
* Tests the modifyLogin function with an nsILoginInfo argument.
*/
add_task(async function test_modifyLogin_nsILoginInfo() {
add_task(function test_modifyLogin_nsILoginInfo() {
let loginInfo = TestData.formLogin();
let updatedLoginInfo = TestData.formLogin({
username: "new username",
@ -318,7 +309,7 @@ add_task(async function test_modifyLogin_nsILoginInfo() {
);
// Add the first form login, then modify it to match the second.
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
Services.logins.modifyLogin(loginInfo, updatedLoginInfo);
// The data should now match the second login.
@ -333,7 +324,7 @@ add_task(async function test_modifyLogin_nsILoginInfo() {
LoginTestUtils.checkLogins([differentLoginInfo]);
// It is now possible to add a login with the old type and origin.
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
LoginTestUtils.checkLogins([loginInfo, differentLoginInfo]);
// Modifying a login to match an existing one should not be possible.
@ -349,7 +340,7 @@ add_task(async function test_modifyLogin_nsILoginInfo() {
/**
* Tests the modifyLogin function with an nsIPropertyBag argument.
*/
add_task(async function test_modifyLogin_nsIProperyBag() {
add_task(function test_modifyLogin_nsIProperyBag() {
let loginInfo = TestData.formLogin();
let updatedLoginInfo = TestData.formLogin({
username: "new username",
@ -376,7 +367,7 @@ add_task(async function test_modifyLogin_nsIProperyBag() {
// Add the first form login, then modify it to match the second, changing
// only some of its properties and checking the behavior with an empty string.
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
Services.logins.modifyLogin(
loginInfo,
newPropertyBag({
@ -414,7 +405,7 @@ add_task(async function test_modifyLogin_nsIProperyBag() {
LoginTestUtils.checkLogins([differentLoginInfo]);
// It is now possible to add a login with the old type and origin.
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
LoginTestUtils.checkLogins([loginInfo, differentLoginInfo]);
// Modifying a login to match an existing one should not be possible.
@ -518,7 +509,7 @@ add_task(function test_deduplicate_keeps_most_recent() {
/**
* Tests handling when adding a login with bad date values
*/
add_task(async function test_addLogin_badDates() {
add_task(function test_addLogin_badDates() {
LoginTestUtils.clearData();
let now = Date.now();
@ -533,7 +524,7 @@ add_task(async function test_addLogin_badDates() {
Assert.ok(!defaultsLogin[pname]);
}
Assert.ok(
!!(await Services.logins.addLoginAsync(defaultsLogin)),
!!Services.logins.addLogin(defaultsLogin),
"Sanity check adding defaults formLogin"
);
Services.logins.removeAllUserFacingLogins();
@ -546,7 +537,7 @@ add_task(async function test_addLogin_badDates() {
})
);
Assert.ok(
!!(await Services.logins.addLoginAsync(loginInfo)),
!!Services.logins.addLogin(loginInfo),
"Check 0 value for " + pname
);
Services.logins.removeAllUserFacingLogins();
@ -560,7 +551,7 @@ add_task(async function test_addLogin_badDates() {
})
);
Assert.ok(
!!(await Services.logins.addLoginAsync(loginInfo)),
!!Services.logins.addLogin(loginInfo),
"Check -1 value for " + pname
);
Services.logins.removeAllUserFacingLogins();
@ -573,8 +564,8 @@ add_task(async function test_addLogin_badDates() {
[pname]: MAX_DATE_MS + 1,
})
);
await Assert.rejects(
Services.logins.addLoginAsync(loginInfo),
Assert.throws(
() => Services.logins.addLogin(loginInfo),
/invalid date properties/
);
Assert.equal(Services.logins.getAllLogins().length, 0);
@ -592,35 +583,33 @@ add_task(async function test_addLogins_badDates() {
let defaultsLogin = TestData.formLogin({
username: "defaults",
});
await Services.logins.addLoginAsync(defaultsLogin);
// -11644473600000 is the value you get if you convert Dec 31 1600 16:07:02 to unix epoch time
let timeCreatedLogin = TestData.formLogin({
username: "tc",
timeCreated: -11644473600000,
});
await Assert.rejects(
Services.logins.addLoginAsync(timeCreatedLogin),
/Can\'t add a login with invalid date properties./
);
let timeLastUsedLogin = TestData.formLogin({
username: "tlu",
timeLastUsed: -11644473600000,
});
await Assert.rejects(
Services.logins.addLoginAsync(timeLastUsedLogin),
/Can\'t add a login with invalid date properties./
);
let timePasswordChangedLogin = TestData.formLogin({
username: "tpc",
timePasswordChanged: -11644473600000,
});
await Assert.rejects(
Services.logins.addLoginAsync(timePasswordChangedLogin),
/Can\'t add a login with invalid date properties./
);
await Services.logins.addLogins([
defaultsLogin,
timeCreatedLogin,
timeLastUsedLogin,
timePasswordChangedLogin,
]);
// none of the logins with invalid dates should have been added
let savedLogins = Services.logins.getAllLogins();
Assert.equal(savedLogins.length, 1);
Services.logins.removeAllUserFacingLogins();
});

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

@ -28,7 +28,9 @@ function resetPrimaryPassword() {
*/
add_task(async function test_logins_decrypt_failure() {
let logins = TestData.loginList();
await Services.logins.addLogins(logins);
for (let loginInfo of logins) {
Services.logins.addLogin(loginInfo);
}
// This makes the existing logins non-decryptable.
resetPrimaryPassword();
@ -55,7 +57,9 @@ add_task(async function test_logins_decrypt_failure() {
Assert.equal(Services.logins.countLogins("", "", ""), logins.length);
// Equivalent logins can be added.
await Services.logins.addLogins(logins);
for (let loginInfo of logins) {
Services.logins.addLogin(loginInfo);
}
LoginTestUtils.checkLogins(logins);
Assert.equal(
(await Services.logins.getAllLoginsAsync()).length,
@ -88,7 +92,7 @@ add_task(async function test_logins_decrypt_failure() {
// Bug 621846 - If a login has a GUID but can't be decrypted, a search for
// that GUID will (correctly) fail. Ensure we can add a new login with that
// same GUID.
add_task(async function test_add_logins_with_decrypt_failure() {
add_task(function test_add_logins_with_decrypt_failure() {
// a login with a GUID.
let login = new LoginInfo(
"http://www.example2.com",
@ -116,7 +120,7 @@ add_task(async function test_add_logins_with_decrypt_failure() {
loginDupeGuid.QueryInterface(Ci.nsILoginMetaInfo);
loginDupeGuid.guid = login.guid;
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
// We can search for this login by GUID.
let searchProp = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
@ -127,13 +131,13 @@ add_task(async function test_add_logins_with_decrypt_failure() {
equal(Services.logins.searchLogins(searchProp).length, 1);
// We should fail to re-add it as it remains good.
await Assert.rejects(
Services.logins.addLoginAsync(login),
Assert.throws(
() => Services.logins.addLogin(login),
/This login already exists./
);
// We should fail to re-add a different login with the same GUID.
await Assert.rejects(
Services.logins.addLoginAsync(loginDupeGuid),
Assert.throws(
() => Services.logins.addLogin(loginDupeGuid),
/specified GUID already exists/
);
@ -144,7 +148,7 @@ add_task(async function test_add_logins_with_decrypt_failure() {
equal(Services.logins.searchLogins(searchProp).length, 0);
// So we should be able to re-add a login with that same GUID.
await Services.logins.addLoginAsync(login);
Services.logins.addLogin(login);
equal(Services.logins.searchLogins(searchProp).length, 1);
Services.logins.removeAllUserFacingLogins();

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

@ -82,9 +82,9 @@ add_task(function test_initialize() {
* Tests the behavior of addLogin with regard to metadata. The logins added
* here are also used by the following tests.
*/
add_task(async function test_addLogin_metainfo() {
add_task(function test_addLogin_metainfo() {
// Add a login without metadata to the database.
await Services.logins.addLoginAsync(gLoginInfo1);
Services.logins.addLogin(gLoginInfo1);
// The object provided to addLogin should not have been modified.
Assert.equal(gLoginInfo1.guid, null);
@ -104,7 +104,7 @@ add_task(async function test_addLogin_metainfo() {
// Add a login without metadata to the database.
let originalLogin = gLoginInfo2.clone().QueryInterface(Ci.nsILoginMetaInfo);
await Services.logins.addLoginAsync(gLoginInfo2);
Services.logins.addLogin(gLoginInfo2);
// The object provided to addLogin should not have been modified.
assertMetaInfoEqual(gLoginInfo2, originalLogin);
@ -114,7 +114,7 @@ add_task(async function test_addLogin_metainfo() {
assertMetaInfoEqual(gLoginMetaInfo2, gLoginInfo2);
// Add an authentication login to the database before continuing.
await Services.logins.addLoginAsync(gLoginInfo3);
Services.logins.addLogin(gLoginInfo3);
gLoginMetaInfo3 = retrieveLoginMatching(gLoginInfo3);
LoginTestUtils.checkLogins([gLoginInfo1, gLoginInfo2, gLoginInfo3]);
});
@ -122,13 +122,13 @@ add_task(async function test_addLogin_metainfo() {
/**
* Tests that adding a login with a duplicate GUID throws an exception.
*/
add_task(async function test_addLogin_metainfo_duplicate() {
add_task(function test_addLogin_metainfo_duplicate() {
let loginInfo = TestData.formLogin({
origin: "http://duplicate.example.com",
guid: gLoginMetaInfo2.guid,
});
await Assert.rejects(
Services.logins.addLoginAsync(loginInfo),
Assert.throws(
() => Services.logins.addLogin(loginInfo),
/specified GUID already exists/
);

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

@ -90,8 +90,10 @@ function checkAllSearches(aQuery, aExpectedCount) {
/**
* Prepare data for the following tests.
*/
add_setup(async () => {
await Services.logins.addLogins(TestData.loginList());
add_task(function test_initialize() {
for (let login of TestData.loginList()) {
Services.logins.addLogin(login);
}
});
/**

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

@ -251,7 +251,9 @@ add_task(async function test_import_from_firefox_various_latest() {
await setupCsv([]);
info("Populate the login list for export");
let logins = LoginTestUtils.testData.loginList();
await Services.logins.addLogins(logins);
for (let loginInfo of logins) {
Services.logins.addLogin(loginInfo);
}
let tmpFilePath = FileTestUtils.getTempFile("logins.csv").path;
await LoginExport.exportAsCSV(tmpFilePath);

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

@ -51,7 +51,7 @@ let TestObserver = {
},
};
add_task(async function test_notifications() {
add_task(function test_notifications() {
let testnum = 0;
let testdesc = "Setup of nsLoginInfo test-users";
@ -88,7 +88,7 @@ add_task(async function test_notifications() {
expectedNotification = "addLogin";
expectedData = testuser1;
await Services.logins.addLoginAsync(testuser1);
Services.logins.addLogin(testuser1);
LoginTestUtils.checkLogins([testuser1]);
Assert.equal(expectedNotification, null); // check that observer got a notification
@ -128,7 +128,7 @@ add_task(async function test_notifications() {
expectedNotification = "addLogin";
expectedData = testuser1;
await Services.logins.addLoginAsync(testuser1);
Services.logins.addLogin(testuser1);
expectedNotification = "removeAllLogins";
expectedData = null;

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

@ -55,8 +55,10 @@ function checkSearch(aQuery, aExpectedCount) {
/**
* Prepare data for the following tests.
*/
add_setup(async () => {
await Services.logins.addLogins(TestData.loginList());
add_task(function test_initialize() {
for (let login of TestData.loginList()) {
Services.logins.addLogin(login);
}
});
/**

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

@ -34,14 +34,14 @@ add_task(async function test_storage_addLogin_nonascii() {
usernameField: "field_" + String.fromCharCode(533, 537, 7570, 345),
passwordField: "field_" + String.fromCharCode(421, 259, 349, 537),
});
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
await reloadAndCheckLoginsGen([loginInfo]);
// Store the string "test" using similarly looking glyphs.
loginInfo = TestData.authLogin({
httpRealm: String.fromCharCode(355, 277, 349, 357),
});
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
await reloadAndCheckLoginsGen([loginInfo]);
});
@ -53,7 +53,7 @@ add_task(async function test_storage_addLogin_newlines() {
username: "user\r\nname",
password: "password\r\n",
});
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
await reloadAndCheckLoginsGen([loginInfo]);
});
@ -64,11 +64,11 @@ add_task(async function test_storage_addLogin_newlines() {
*/
add_task(async function test_storage_addLogin_dot() {
let loginInfo = TestData.formLogin({ origin: ".", passwordField: "." });
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
await reloadAndCheckLoginsGen([loginInfo]);
loginInfo = TestData.authLogin({ httpRealm: "." });
await Services.logins.addLoginAsync(loginInfo);
Services.logins.addLogin(loginInfo);
await reloadAndCheckLoginsGen([loginInfo]);
});
@ -88,6 +88,8 @@ add_task(async function test_storage_addLogin_parentheses() {
TestData.authLogin({ origin: "http://parens(example).example.com" }),
TestData.authLogin({ origin: "http://parens)example(.example.com" }),
];
await Services.logins.addLogins(loginList);
for (let loginInfo of loginList) {
Services.logins.addLogin(loginInfo);
}
await reloadAndCheckLoginsGen(loginList);
});

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

@ -111,7 +111,7 @@ function testHistogram(histogramId, expectedNonZeroRanges) {
* Enable local telemetry recording for the duration of the tests, and prepare
* the test data that will be used by the following tests.
*/
add_setup(async () => {
add_task(function test_initialize() {
let oldCanRecord = Services.telemetry.canRecordExtended;
Services.telemetry.canRecordExtended = true;
registerCleanupFunction(function() {
@ -119,16 +119,16 @@ add_setup(async () => {
});
let uniqueNumber = 1;
let logins = [];
for (let loginModifications of StatisticsTestData) {
loginModifications.origin = `http://${uniqueNumber++}.example.com`;
let login;
if (typeof loginModifications.httpRealm != "undefined") {
logins.push(TestData.authLogin(loginModifications));
login = TestData.authLogin(loginModifications);
} else {
logins.push(TestData.formLogin(loginModifications));
login = TestData.formLogin(loginModifications);
}
Services.logins.addLogin(login);
}
await Services.logins.addLogins(logins);
});
/**

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

@ -10,11 +10,11 @@ add_setup(async () => {
add_task(async function test_vulnerable_password_methods() {
const storageJSON = Services.logins.wrappedJSObject._storage.wrappedJSObject;
const logins = TestData.loginList();
let logins = TestData.loginList();
Assert.greater(logins.length, 0, "Initial logins length should be > 0.");
for (const loginInfo of logins) {
await Services.logins.addLoginAsync(loginInfo);
for (let loginInfo of logins) {
Services.logins.addLogin(loginInfo);
Assert.ok(
!storageJSON.isPotentiallyVulnerablePassword(loginInfo),
"No logins should be vulnerable until addVulnerablePasswords is called."
@ -28,7 +28,7 @@ add_task(async function test_vulnerable_password_methods() {
storageJSON.isPotentiallyVulnerablePassword(vulnerableLogin),
"Login should be vulnerable after calling addVulnerablePassword."
);
for (const loginInfo of logins) {
for (let loginInfo of logins) {
Assert.ok(
!storageJSON.isPotentiallyVulnerablePassword(loginInfo),
"No other logins should be vulnerable when addVulnerablePassword is called" +
@ -38,7 +38,7 @@ add_task(async function test_vulnerable_password_methods() {
storageJSON.clearAllPotentiallyVulnerablePasswords();
for (const loginInfo of logins) {
for (let loginInfo of logins) {
Assert.ok(
!storageJSON.isPotentiallyVulnerablePassword(loginInfo),
"No logins should be vulnerable when clearAllPotentiallyVulnerablePasswords is called."