summaryrefslogtreecommitdiffstats
path: root/browser/components/aboutlogins/tests/browser/browser_primaryPassword.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/aboutlogins/tests/browser/browser_primaryPassword.js')
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_primaryPassword.js282
1 files changed, 282 insertions, 0 deletions
diff --git a/browser/components/aboutlogins/tests/browser/browser_primaryPassword.js b/browser/components/aboutlogins/tests/browser/browser_primaryPassword.js
new file mode 100644
index 0000000000..79a1e9a1da
--- /dev/null
+++ b/browser/components/aboutlogins/tests/browser/browser_primaryPassword.js
@@ -0,0 +1,282 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function waitForLoginCountToReach(browser, loginCount) {
+ return SpecialPowers.spawn(
+ browser,
+ [loginCount],
+ async expectedLoginCount => {
+ let loginList = Cu.waiveXrays(
+ content.document.querySelector("login-list")
+ );
+ await ContentTaskUtils.waitForCondition(() => {
+ return loginList._loginGuidsSortedOrder.length == expectedLoginCount;
+ });
+ return loginList._loginGuidsSortedOrder.length;
+ }
+ );
+}
+
+add_setup(async function () {
+ await addLogin(TEST_LOGIN1);
+ registerCleanupFunction(() => {
+ Services.logins.removeAllUserFacingLogins();
+ LoginTestUtils.primaryPassword.disable();
+ });
+});
+
+add_task(async function test() {
+ // Confirm that the mocking of the OS auth dialog isn't enabled so the
+ // test will timeout if a real OS auth dialog is shown. We don't show
+ // the OS auth dialog when Primary Password is enabled.
+ Assert.equal(
+ Services.prefs.getStringPref(
+ "toolkit.osKeyStore.unofficialBuildOnlyLogin",
+ ""
+ ),
+ "",
+ "Pref should be set to default value of empty string to start the test"
+ );
+ LoginTestUtils.primaryPassword.enable();
+
+ let mpDialogShown = forceAuthTimeoutAndWaitForMPDialog("cancel");
+ await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ url: "about:logins",
+ });
+ await mpDialogShown;
+
+ let browser = gBrowser.selectedBrowser;
+ let logins = await waitForLoginCountToReach(browser, 0);
+ Assert.equal(
+ logins,
+ 0,
+ "No logins should be displayed when MP is set and unauthenticated"
+ );
+
+ let notification;
+ await TestUtils.waitForCondition(
+ () =>
+ (notification = gBrowser
+ .getNotificationBox()
+ .getNotificationWithValue("primary-password-login-required")),
+ "waiting for primary-password-login-required notification"
+ );
+
+ Assert.ok(
+ notification,
+ "primary-password-login-required notification should be visible"
+ );
+
+ let buttons = notification.buttonContainer.querySelectorAll(
+ ".notification-button"
+ );
+ Assert.equal(buttons.length, 1, "Should have one button.");
+
+ let refreshPromise = BrowserTestUtils.browserLoaded(browser);
+ // Sign in with the Primary Password this time the dialog is shown
+ mpDialogShown = forceAuthTimeoutAndWaitForMPDialog("authenticate");
+ // Click the button to reload the page.
+ buttons[0].click();
+ await refreshPromise;
+ info("Page reloaded");
+
+ await mpDialogShown;
+ info("Primary Password dialog shown and authenticated");
+
+ logins = await waitForLoginCountToReach(browser, 1);
+ Assert.equal(
+ logins,
+ 1,
+ "Logins should be displayed when MP is set and authenticated"
+ );
+
+ // Show MP dialog when Copy Password button clicked
+ mpDialogShown = forceAuthTimeoutAndWaitForMPDialog("cancel");
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
+ let loginItem = content.document.querySelector("login-item");
+ let copyButton = loginItem.shadowRoot.querySelector(
+ ".copy-password-button"
+ );
+ copyButton.click();
+ });
+ await mpDialogShown;
+ info("Primary Password dialog shown and canceled");
+ mpDialogShown = forceAuthTimeoutAndWaitForMPDialog("authenticate");
+ info("Clicking copy password button again");
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
+ let loginItem = content.document.querySelector("login-item");
+ let copyButton = loginItem.shadowRoot.querySelector(
+ ".copy-password-button"
+ );
+ copyButton.click();
+ });
+ await mpDialogShown;
+ info("Primary Password dialog shown and authenticated");
+ await SpecialPowers.spawn(browser, [], async function () {
+ let loginItem = content.document.querySelector("login-item");
+ let copyButton = loginItem.shadowRoot.querySelector(
+ ".copy-password-button"
+ );
+ await ContentTaskUtils.waitForCondition(() => {
+ return copyButton.disabled;
+ }, "Waiting for copy button to be disabled");
+ info("Password was copied to clipboard");
+ });
+
+ // Show MP dialog when Reveal Password checkbox is checked if not on a new login
+ mpDialogShown = forceAuthTimeoutAndWaitForMPDialog("cancel");
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
+ let loginItem = content.document.querySelector("login-item");
+ let revealCheckbox = loginItem.shadowRoot.querySelector(
+ ".reveal-password-checkbox"
+ );
+ revealCheckbox.click();
+ });
+ await mpDialogShown;
+ info("Primary Password dialog shown and canceled");
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
+ let loginItem = content.document.querySelector("login-item");
+ let revealCheckbox = loginItem.shadowRoot.querySelector(
+ ".reveal-password-checkbox"
+ );
+ Assert.ok(
+ !revealCheckbox.checked,
+ "reveal checkbox should be unchecked if MP dialog canceled"
+ );
+ });
+ mpDialogShown = forceAuthTimeoutAndWaitForMPDialog("authenticate");
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
+ let loginItem = content.document.querySelector("login-item");
+ let revealCheckbox = loginItem.shadowRoot.querySelector(
+ ".reveal-password-checkbox"
+ );
+ revealCheckbox.click();
+ });
+ await mpDialogShown;
+ info("Primary Password dialog shown and authenticated");
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
+ let loginItem = content.document.querySelector("login-item");
+ let revealCheckbox = loginItem.shadowRoot.querySelector(
+ ".reveal-password-checkbox"
+ );
+ Assert.ok(
+ revealCheckbox.checked,
+ "reveal checkbox should be checked if MP dialog authenticated"
+ );
+ });
+
+ info("Test toggling the password visibility on a new login");
+ await SpecialPowers.spawn(browser, [], async function createNewToggle() {
+ let createButton = content.document
+ .querySelector("login-list")
+ .shadowRoot.querySelector(".create-login-button");
+ createButton.click();
+
+ let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
+ let passwordField = loginItem.shadowRoot.querySelector(
+ "input[name='password']"
+ );
+ let revealCheckbox = loginItem.shadowRoot.querySelector(
+ ".reveal-password-checkbox"
+ );
+ Assert.ok(ContentTaskUtils.is_visible(revealCheckbox), "Toggle visible");
+ Assert.ok(!revealCheckbox.checked, "Not revealed initially");
+ Assert.equal(passwordField.type, "password", "type is password");
+ revealCheckbox.click();
+
+ await ContentTaskUtils.waitForCondition(() => {
+ return passwordField.type == "text";
+ }, "Waiting for type='text'");
+ Assert.ok(revealCheckbox.checked, "Not revealed after click");
+
+ let cancelButton = loginItem.shadowRoot.querySelector(".cancel-button");
+ cancelButton.click();
+ });
+
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
+ const loginList = Cu.waiveXrays(
+ content.document.querySelector("login-list")
+ );
+
+ const loginFilter = Cu.waiveXrays(
+ loginList.shadowRoot.querySelector("login-filter")
+ );
+ loginFilter.value = "pass1";
+ Assert.equal(
+ loginList._list.querySelectorAll(
+ ".login-list-item[data-guid]:not([hidden])"
+ ).length,
+ 1,
+ "login-list should show corresponding result when primary password is enabled"
+ );
+ loginFilter.value = "";
+ Assert.equal(
+ loginList._list.querySelectorAll(
+ ".login-list-item[data-guid]:not([hidden])"
+ ).length,
+ 1,
+ "login-list should show all results since the filter is empty"
+ );
+ });
+ LoginTestUtils.primaryPassword.disable();
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
+ Cu.waiveXrays(content).AboutLoginsUtils.primaryPasswordEnabled = false;
+ const loginList = Cu.waiveXrays(
+ content.document.querySelector("login-list")
+ );
+ const loginFilter = Cu.waiveXrays(
+ loginList.shadowRoot.querySelector("login-filter")
+ );
+ loginFilter.value = "pass1";
+ Assert.equal(
+ loginList._list.querySelectorAll(
+ ".login-list-item[data-guid]:not([hidden])"
+ ).length,
+ 1,
+ "login-list should show login with matching password since MP is disabled"
+ );
+ });
+
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+add_task(async function test_login_item_after_successful_auth() {
+ // Confirm that the mocking of the OS auth dialog isn't enabled so the
+ // test will timeout if a real OS auth dialog is shown. We don't show
+ // the OS auth dialog when Primary Password is enabled.
+ Assert.equal(
+ Services.prefs.getStringPref(
+ "toolkit.osKeyStore.unofficialBuildOnlyLogin",
+ ""
+ ),
+ "",
+ "Pref should be set to default value of empty string to start the test"
+ );
+ LoginTestUtils.primaryPassword.enable();
+
+ let mpDialogShown = forceAuthTimeoutAndWaitForMPDialog("authenticate");
+ await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ url: "about:logins",
+ });
+ await mpDialogShown;
+
+ let browser = gBrowser.selectedBrowser;
+ let logins = await waitForLoginCountToReach(browser, 1);
+ Assert.equal(
+ logins,
+ 1,
+ "Logins should be displayed when MP is set and authenticated"
+ );
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
+ let loginItem = content.document.querySelector("login-item");
+ Assert.ok(
+ !loginItem.classList.contains("no-logins"),
+ "Login item should have content after MP is authenticated"
+ );
+ });
+
+ LoginTestUtils.primaryPassword.disable();
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});