From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../components/aboutlogins/tests/browser/head.js | 225 +++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 browser/components/aboutlogins/tests/browser/head.js (limited to 'browser/components/aboutlogins/tests/browser/head.js') diff --git a/browser/components/aboutlogins/tests/browser/head.js b/browser/components/aboutlogins/tests/browser/head.js new file mode 100644 index 0000000000..2aec0e632a --- /dev/null +++ b/browser/components/aboutlogins/tests/browser/head.js @@ -0,0 +1,225 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +let { LoginBreaches } = ChromeUtils.importESModule( + "resource:///modules/LoginBreaches.sys.mjs" +); +let { RemoteSettings } = ChromeUtils.importESModule( + "resource://services-settings/remote-settings.sys.mjs" +); +let { _AboutLogins } = ChromeUtils.importESModule( + "resource:///actors/AboutLoginsParent.sys.mjs" +); +let { OSKeyStoreTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/OSKeyStoreTestUtils.sys.mjs" +); +var { LoginTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/LoginTestUtils.sys.mjs" +); + +let nsLoginInfo = new Components.Constructor( + "@mozilla.org/login-manager/loginInfo;1", + Ci.nsILoginInfo, + "init" +); + +let TEST_LOGIN1 = new nsLoginInfo( + "https://example.com", + "https://example.com", + null, + "user1", + "pass1", + "username", + "password" +); +let TEST_LOGIN2 = new nsLoginInfo( + "https://2.example.com", + "https://2.example.com", + null, + "user2", + "pass2", + "username", + "password" +); + +let TEST_LOGIN3 = new nsLoginInfo( + "https://breached.example.com", + "https://breached.example.com", + null, + "breachedLogin1", + "pass3", + "breachedLogin", + "password" +); +TEST_LOGIN3.QueryInterface(Ci.nsILoginMetaInfo).timePasswordChanged = 123456; + +async function addLogin(login) { + const result = await Services.logins.addLoginAsync(login); + registerCleanupFunction(() => { + let matchData = Cc["@mozilla.org/hash-property-bag;1"].createInstance( + Ci.nsIWritablePropertyBag2 + ); + matchData.setPropertyAsAUTF8String("guid", result.guid); + + let logins = Services.logins.searchLogins(matchData); + if (!logins.length) { + return; + } + // Use the login that was returned from searchLogins + // in case the initial login object was changed by the test code, + // since removeLogin makes sure that the login argument exactly + // matches the login that it will be removing. + Services.logins.removeLogin(logins[0]); + }); + return result; +} + +let EXPECTED_BREACH = null; +let EXPECTED_ERROR_MESSAGE = null; +add_setup(async function setup_head() { + const db = RemoteSettings(LoginBreaches.REMOTE_SETTINGS_COLLECTION).db; + if (EXPECTED_BREACH) { + await db.create(EXPECTED_BREACH, { + useRecordId: true, + }); + } + await db.importChanges({}, Date.now()); + if (EXPECTED_BREACH) { + await RemoteSettings(LoginBreaches.REMOTE_SETTINGS_COLLECTION).emit( + "sync", + { data: { current: [EXPECTED_BREACH] } } + ); + } + + SpecialPowers.registerConsoleListener(function onConsoleMessage(msg) { + if (msg.isWarning || !msg.errorMessage) { + // Ignore warnings and non-errors. + return; + } + + if (msg.errorMessage.includes('Unknown event: ["jsonfile", "load"')) { + // Ignore telemetry errors from JSONFile.sys.mjs. + return; + } + + if ( + msg.errorMessage == "Refreshing device list failed." || + msg.errorMessage == "Skipping device list refresh; not signed in" + ) { + // Ignore errors from browser-sync.js. + return; + } + if ( + msg.errorMessage.includes( + "ReferenceError: MigrationWizard is not defined" + ) + ) { + // todo(Bug 1587237): Ignore error when loading the Migration Wizard in automation. + return; + } + if ( + msg.errorMessage.includes("Error detecting Chrome profiles") || + msg.errorMessage.includes( + "Library/Application Support/Chromium/Local State (No such file or directory)" + ) || + msg.errorMessage.includes( + "Library/Application Support/Google/Chrome/Local State (No such file or directory)" + ) + ) { + // Ignore errors that can occur when the migrator is looking for a + // Chrome/Chromium profile + return; + } + if (msg.errorMessage.includes("Can't find profile directory.")) { + // Ignore error messages for no profile found in old XULStore.jsm + return; + } + if (msg.errorMessage.includes("Error reading typed URL history")) { + // The Migrator when opened can log this exception if there is no Edge + // history on the machine. + return; + } + if (msg.errorMessage.includes(EXPECTED_ERROR_MESSAGE)) { + return; + } + if (msg.errorMessage == "FILE_FORMAT_ERROR") { + // Ignore errors handled by the error message dialog. + return; + } + if ( + msg.errorMessage == + "NotFoundError: No such JSWindowActor 'MarionetteEvents'" + ) { + // Ignore MarionetteEvents error (Bug 1730837, Bug 1710079). + return; + } + Assert.ok(false, msg.message || msg.errorMessage); + }); + + registerCleanupFunction(async () => { + EXPECTED_ERROR_MESSAGE = null; + await db.clear(); + Services.telemetry.clearEvents(); + SpecialPowers.postConsoleSentinel(); + }); +}); + +/** + * Waits for the primary password prompt and performs an action. + * @param {string} action Set to "authenticate" to log in or "cancel" to + * close the dialog without logging in. + */ +function waitForMPDialog(action, aWindow = window) { + const BRAND_BUNDLE = Services.strings.createBundle( + "chrome://branding/locale/brand.properties" + ); + const BRAND_FULL_NAME = BRAND_BUNDLE.GetStringFromName("brandFullName"); + let dialogShown = TestUtils.topicObserved("common-dialog-loaded"); + return dialogShown.then(function ([subject]) { + let dialog = subject.Dialog; + let expected = "Password Required - " + BRAND_FULL_NAME; + Assert.equal( + dialog.args.title, + expected, + "Dialog is the Primary Password dialog" + ); + if (action == "authenticate") { + SpecialPowers.wrap(dialog.ui.password1Textbox).setUserInput( + LoginTestUtils.primaryPassword.primaryPassword + ); + dialog.ui.button0.click(); + } else if (action == "cancel") { + dialog.ui.button1.click(); + } + return BrowserTestUtils.waitForEvent(aWindow, "DOMModalDialogClosed"); + }); +} + +/** + * Allows for tests to reset the MP auth expiration and + * return a promise that will resolve after the MP dialog has + * been presented. + * + * @param {string} action Set to "authenticate" to log in or "cancel" to + * close the dialog without logging in. + * @returns {Promise} Resolves after the MP dialog has been presented and actioned upon + */ +function forceAuthTimeoutAndWaitForMPDialog(action, aWindow = window) { + const AUTH_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes (duplicated from AboutLoginsParent.sys.mjs) + _AboutLogins._authExpirationTime -= AUTH_TIMEOUT_MS + 1; + return waitForMPDialog(action, aWindow); +} + +/** + * Allows for tests to reset the OS auth expiration and + * return a promise that will resolve after the OS auth dialog has + * been presented. + * + * @param {bool} loginResult True if the auth prompt should pass, otherwise false will fail + * @returns {Promise} Resolves after the OS auth dialog has been presented + */ +function forceAuthTimeoutAndWaitForOSKeyStoreLogin({ loginResult }) { + const AUTH_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes (duplicated from AboutLoginsParent.sys.mjs) + _AboutLogins._authExpirationTime -= AUTH_TIMEOUT_MS + 1; + return OSKeyStoreTestUtils.waitForOSKeyStoreLogin(loginResult); +} -- cgit v1.2.3