summaryrefslogtreecommitdiffstats
path: root/browser/components/aboutlogins
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/aboutlogins')
-rw-r--r--browser/components/aboutlogins/AboutLoginsChild.sys.mjs6
-rw-r--r--browser/components/aboutlogins/AboutLoginsParent.sys.mjs21
-rw-r--r--browser/components/aboutlogins/LoginBreaches.sys.mjs23
-rw-r--r--browser/components/aboutlogins/content/aboutLogins.html1
-rw-r--r--browser/components/aboutlogins/content/aboutLoginsImportReport.html1
-rw-r--r--browser/components/aboutlogins/content/components/login-item.css21
-rw-r--r--browser/components/aboutlogins/tests/browser/browser.toml1
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_aaa_eventTelemetry_run_first.js14
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_alertDismissedAfterChangingPassword.js11
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_contextmenuFillLogins.js6
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_copyToClipboardButton.js6
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_createLogin.js9
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_deleteLogin.js5
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_loginItemErrors.js5
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_openExport.js3
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_openSite.js5
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_osAuthDialog.js348
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_removeAllDialog.js12
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_tabKeyNav.js15
-rw-r--r--browser/components/aboutlogins/tests/browser/browser_updateLogin.js37
-rw-r--r--browser/components/aboutlogins/tests/browser/head.js33
-rw-r--r--browser/components/aboutlogins/tests/chrome/test_confirm_delete_dialog.html5
22 files changed, 443 insertions, 145 deletions
diff --git a/browser/components/aboutlogins/AboutLoginsChild.sys.mjs b/browser/components/aboutlogins/AboutLoginsChild.sys.mjs
index 3fcdf77923..c7059d8f40 100644
--- a/browser/components/aboutlogins/AboutLoginsChild.sys.mjs
+++ b/browser/components/aboutlogins/AboutLoginsChild.sys.mjs
@@ -160,7 +160,11 @@ export class AboutLoginsChild extends JSWindowActorChild {
}
#aboutLoginsCopyLoginDetail(detail) {
- lazy.ClipboardHelper.copyString(detail, lazy.ClipboardHelper.Sensitive);
+ lazy.ClipboardHelper.copyString(
+ detail,
+ this.windowContext,
+ lazy.ClipboardHelper.Sensitive
+ );
}
#aboutLoginsCreateLogin(login) {
diff --git a/browser/components/aboutlogins/AboutLoginsParent.sys.mjs b/browser/components/aboutlogins/AboutLoginsParent.sys.mjs
index 28f56c2172..4342e60296 100644
--- a/browser/components/aboutlogins/AboutLoginsParent.sys.mjs
+++ b/browser/components/aboutlogins/AboutLoginsParent.sys.mjs
@@ -17,7 +17,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
LoginExport: "resource://gre/modules/LoginExport.sys.mjs",
LoginHelper: "resource://gre/modules/LoginHelper.sys.mjs",
MigrationUtils: "resource:///modules/MigrationUtils.sys.mjs",
- OSKeyStore: "resource://gre/modules/OSKeyStore.sys.mjs",
UIState: "resource://services-sync/UIState.sys.mjs",
});
@@ -38,12 +37,6 @@ XPCOMUtils.defineLazyPreferenceGetter(
);
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
- "OS_AUTH_ENABLED",
- "signon.management.page.os-auth.enabled",
- true
-);
-XPCOMUtils.defineLazyPreferenceGetter(
- lazy,
"VULNERABLE_PASSWORDS_ENABLED",
"signon.management.page.vulnerable-passwords.enabled",
false
@@ -266,11 +259,15 @@ export class AboutLoginsParent extends JSWindowActorParent {
let messageText = { value: "NOT SUPPORTED" };
let captionText = { value: "" };
+ const isOSAuthEnabled = lazy.LoginHelper.getOSAuthEnabled(
+ lazy.LoginHelper.OS_AUTH_FOR_PASSWORDS_PREF
+ );
+
// This feature is only supported on Windows and macOS
// but we still call in to OSKeyStore on Linux to get
// the proper auth_details for Telemetry.
// See bug 1614874 for Linux support.
- if (lazy.OS_AUTH_ENABLED && lazy.OSKeyStore.canReauth()) {
+ if (isOSAuthEnabled) {
messageId += "-" + AppConstants.platform;
[messageText, captionText] = await lazy.AboutLoginsL10n.formatMessages([
{
@@ -284,7 +281,7 @@ export class AboutLoginsParent extends JSWindowActorParent {
let { isAuthorized, telemetryEvent } = await lazy.LoginHelper.requestReauth(
this.browsingContext.embedderElement,
- lazy.OS_AUTH_ENABLED,
+ isOSAuthEnabled,
AboutLogins._authExpirationTime,
messageText.value,
captionText.value
@@ -378,11 +375,15 @@ export class AboutLoginsParent extends JSWindowActorParent {
let messageText = { value: "NOT SUPPORTED" };
let captionText = { value: "" };
+ const isOSAuthEnabled = lazy.LoginHelper.getOSAuthEnabled(
+ lazy.LoginHelper.OS_AUTH_FOR_PASSWORDS_PREF
+ );
+
// This feature is only supported on Windows and macOS
// but we still call in to OSKeyStore on Linux to get
// the proper auth_details for Telemetry.
// See bug 1614874 for Linux support.
- if (lazy.OSKeyStore.canReauth()) {
+ if (isOSAuthEnabled) {
const messageId =
EXPORT_PASSWORD_OS_AUTH_DIALOG_MESSAGE_IDS[AppConstants.platform];
if (!messageId) {
diff --git a/browser/components/aboutlogins/LoginBreaches.sys.mjs b/browser/components/aboutlogins/LoginBreaches.sys.mjs
index b2a0af5e39..496e5de575 100644
--- a/browser/components/aboutlogins/LoginBreaches.sys.mjs
+++ b/browser/components/aboutlogins/LoginBreaches.sys.mjs
@@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
+
/**
* Manages breach alerts for saved logins using data from Firefox Monitor via
* RemoteSettings.
@@ -16,6 +18,13 @@ ChromeUtils.defineESModuleGetters(lazy, {
"resource://services-settings/RemoteSettingsClient.sys.mjs",
});
+XPCOMUtils.defineLazyPreferenceGetter(
+ lazy,
+ "VULNERABLE_PASSWORDS_ENABLED",
+ "signon.management.page.vulnerable-passwords.enabled",
+ false
+);
+
export const LoginBreaches = {
REMOTE_SETTINGS_COLLECTION: "fxmonitor-breaches",
@@ -138,6 +147,20 @@ export const LoginBreaches = {
return vulnerablePasswordsByLoginGUID;
},
+ recordBreachAlertDismissal(loginGuid) {
+ const storageJSON = Services.logins.wrappedJSObject._storage;
+ return storageJSON.recordBreachAlertDismissal(loginGuid);
+ },
+
+ isVulnerablePassword(login) {
+ if (!lazy.VULNERABLE_PASSWORDS_ENABLED) {
+ return false;
+ }
+
+ const storageJSON = Services.logins.wrappedJSObject._storage;
+ return storageJSON.isPotentiallyVulnerablePassword(login);
+ },
+
async clearAllPotentiallyVulnerablePasswords() {
await Services.logins.initializationPromise;
const storageJSON = Services.logins.wrappedJSObject._storage;
diff --git a/browser/components/aboutlogins/content/aboutLogins.html b/browser/components/aboutlogins/content/aboutLogins.html
index 67712c8f29..a0c04149e7 100644
--- a/browser/components/aboutlogins/content/aboutLogins.html
+++ b/browser/components/aboutlogins/content/aboutLogins.html
@@ -11,7 +11,6 @@
<title data-l10n-id="about-logins-page-title-name"></title>
<link rel="localization" href="branding/brand.ftl">
<link rel="localization" href="browser/aboutLogins.ftl">
- <link rel="localization" href="toolkit/branding/accounts.ftl">
<link rel="localization" href="toolkit/branding/brandings.ftl">
<script type="module" src="chrome://browser/content/aboutlogins/components/confirmation-dialog.mjs"></script>
<script type="module" src="chrome://browser/content/aboutlogins/components/remove-logins-dialog.mjs"></script>
diff --git a/browser/components/aboutlogins/content/aboutLoginsImportReport.html b/browser/components/aboutlogins/content/aboutLoginsImportReport.html
index 9ab2641ca2..c9956e2cca 100644
--- a/browser/components/aboutlogins/content/aboutLoginsImportReport.html
+++ b/browser/components/aboutlogins/content/aboutLoginsImportReport.html
@@ -14,7 +14,6 @@
<title data-l10n-id="about-logins-import-report-page-title"></title>
<link rel="localization" href="branding/brand.ftl" />
<link rel="localization" href="browser/aboutLogins.ftl" />
- <link rel="localization" href="toolkit/branding/accounts.ftl" />
<link rel="localization" href="toolkit/branding/brandings.ftl" />
<script
type="module"
diff --git a/browser/components/aboutlogins/content/components/login-item.css b/browser/components/aboutlogins/content/components/login-item.css
index 4a3d85d859..e9e91f78ed 100644
--- a/browser/components/aboutlogins/content/components/login-item.css
+++ b/browser/components/aboutlogins/content/components/login-item.css
@@ -64,11 +64,6 @@ form {
display: none;
}
-input[type="password"],
-input[type="text"],
-input[type="url"] {
- text-align: match-parent !important; /* override `all: unset` in the rule below */
-}
:host(:not([data-editing])) input[type="password"]:read-only,
input[type="text"]:read-only,
@@ -82,6 +77,17 @@ input[type="url"]:read-only {
width: 100%;
}
+input:is([type="password"], [type="text"], [type="url"]) {
+ /* Override all: unset above */
+ appearance: textfield !important;
+ text-align: match-parent !important;
+}
+
+input.password-display,
+input[name="password"] {
+ font-family: monospace !important; /* Override all: unset above */
+}
+
/* We can't use `margin-inline-start` here because we force
* the input to have dir="ltr", so we set the margin manually
* using the parent element's directionality. */
@@ -197,11 +203,6 @@ moz-button-group,
box-shadow: none;
}
-input.password-display,
-input[name="password"] {
- font-family: monospace !important; /* override `all: unset` in the rule above */
-}
-
.reveal-password-checkbox {
appearance: none;
background-image: url("resource://gre-resources/password.svg");
diff --git a/browser/components/aboutlogins/tests/browser/browser.toml b/browser/components/aboutlogins/tests/browser/browser.toml
index 0b38e0dda1..07c49c4c88 100644
--- a/browser/components/aboutlogins/tests/browser/browser.toml
+++ b/browser/components/aboutlogins/tests/browser/browser.toml
@@ -2,7 +2,6 @@
support-files = ["head.js"]
prefs = [
"signon.management.page.vulnerable-passwords.enabled=true",
- "signon.management.page.os-auth.enabled=true",
"toolkit.telemetry.ipcBatchTimeout=10", # lower the interval for event telemetry in the content process to update the parent process
]
# Run first so content events from previous tests won't trickle in.
diff --git a/browser/components/aboutlogins/tests/browser/browser_aaa_eventTelemetry_run_first.js b/browser/components/aboutlogins/tests/browser/browser_aaa_eventTelemetry_run_first.js
index 52b2eb02a2..4f3cdbe48e 100644
--- a/browser/components/aboutlogins/tests/browser/browser_aaa_eventTelemetry_run_first.js
+++ b/browser/components/aboutlogins/tests/browser/browser_aaa_eventTelemetry_run_first.js
@@ -72,7 +72,10 @@ add_task(async function test_telemetry_events() {
await LoginTestUtils.telemetry.waitForEventCount(3);
if (OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
- let reauthObserved = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ let reauthObserved = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ reauthObserved = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
let loginItem = content.document.querySelector("login-item");
let copyButton = loginItem.shadowRoot.querySelector(
@@ -106,9 +109,12 @@ add_task(async function test_telemetry_events() {
// Show the password
if (OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
- let reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
- loginResult: true,
- });
+ let reauthObserved = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
+ loginResult: true,
+ });
+ }
nextTelemetryEventCount++; // An extra event is observed for the reauth event.
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
let loginItem = content.document.querySelector("login-item");
diff --git a/browser/components/aboutlogins/tests/browser/browser_alertDismissedAfterChangingPassword.js b/browser/components/aboutlogins/tests/browser/browser_alertDismissedAfterChangingPassword.js
index b2b036121a..b28dcf25ee 100644
--- a/browser/components/aboutlogins/tests/browser/browser_alertDismissedAfterChangingPassword.js
+++ b/browser/components/aboutlogins/tests/browser/browser_alertDismissedAfterChangingPassword.js
@@ -32,6 +32,7 @@ add_setup(async function () {
gBrowser,
url: "about:logins",
});
+
registerCleanupFunction(() => {
BrowserTestUtils.removeTab(gBrowser.selectedTab);
Services.logins.removeAllUserFacingLogins();
@@ -104,9 +105,13 @@ add_task(async function test_added_login_shows_breach_warning() {
return;
}
- let reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
- loginResult: true,
- });
+ let reauthObserved = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
+ loginResult: true,
+ });
+ }
+
// Change the password on the breached login and check that the
// login is no longer marked as breached. The vulnerable login
// should still be marked as vulnerable afterwards.
diff --git a/browser/components/aboutlogins/tests/browser/browser_contextmenuFillLogins.js b/browser/components/aboutlogins/tests/browser/browser_contextmenuFillLogins.js
index ee1527d792..55180435c7 100644
--- a/browser/components/aboutlogins/tests/browser/browser_contextmenuFillLogins.js
+++ b/browser/components/aboutlogins/tests/browser/browser_contextmenuFillLogins.js
@@ -32,8 +32,10 @@ if (OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
gTests[gTests.length] = {
name: "test contextmenu on password field in edit login view",
async setup(browser) {
- let osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
-
+ let osAuthDialogShown = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
// load up the edit login view
await SpecialPowers.spawn(
browser,
diff --git a/browser/components/aboutlogins/tests/browser/browser_copyToClipboardButton.js b/browser/components/aboutlogins/tests/browser/browser_copyToClipboardButton.js
index 8b0d3b7bf6..1f6eff8806 100644
--- a/browser/components/aboutlogins/tests/browser/browser_copyToClipboardButton.js
+++ b/browser/components/aboutlogins/tests/browser/browser_copyToClipboardButton.js
@@ -49,9 +49,11 @@ add_task(async function test() {
info(
"waiting for " + testObj.expectedValue + " to be placed on clipboard"
);
- let reauthObserved = true;
+ let reauthObserved = Promise.resolve();
if (testObj.copyButtonSelector.includes("password")) {
- reauthObserved = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ if (OSKeyStore.canReauth()) {
+ reauthObserved = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
}
await SimpleTest.promiseClipboardChange(
diff --git a/browser/components/aboutlogins/tests/browser/browser_createLogin.js b/browser/components/aboutlogins/tests/browser/browser_createLogin.js
index 4aac8cece1..46c4487ba3 100644
--- a/browser/components/aboutlogins/tests/browser/browser_createLogin.js
+++ b/browser/components/aboutlogins/tests/browser/browser_createLogin.js
@@ -232,9 +232,12 @@ add_task(async function test_create_login() {
continue;
}
- let reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
- loginResult: true,
- });
+ let reauthObserved = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
+ loginResult: true,
+ });
+ }
await SpecialPowers.spawn(browser, [], async () => {
let loginItem = Cu.waiveXrays(
content.document.querySelector("login-item")
diff --git a/browser/components/aboutlogins/tests/browser/browser_deleteLogin.js b/browser/components/aboutlogins/tests/browser/browser_deleteLogin.js
index 90195d0e0a..4fc250523c 100644
--- a/browser/components/aboutlogins/tests/browser/browser_deleteLogin.js
+++ b/browser/components/aboutlogins/tests/browser/browser_deleteLogin.js
@@ -71,7 +71,10 @@ add_task(async function test_login_item() {
}, "Waiting for login item to get populated");
Assert.ok(loginItemPopulated, "The login item should get populated");
});
- let reauthObserved = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ let reauthObserved = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ reauthObserved = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
await SpecialPowers.spawn(browser, [], async () => {
let loginItem = Cu.waiveXrays(
content.document.querySelector("login-item")
diff --git a/browser/components/aboutlogins/tests/browser/browser_loginItemErrors.js b/browser/components/aboutlogins/tests/browser/browser_loginItemErrors.js
index a78f49d3c9..1789d47b8e 100644
--- a/browser/components/aboutlogins/tests/browser/browser_loginItemErrors.js
+++ b/browser/components/aboutlogins/tests/browser/browser_loginItemErrors.js
@@ -107,7 +107,10 @@ add_task(async function test_showLoginItemErrors() {
// The rest of the test uses Edit mode which causes an OS prompt in official builds.
return;
}
- let reauthObserved = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ let reauthObserved = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ reauthObserved = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
await SpecialPowers.spawn(
browser,
[[LoginHelper.loginToVanillaObject(LOGIN_TO_UPDATE), LOGIN_UPDATES]],
diff --git a/browser/components/aboutlogins/tests/browser/browser_openExport.js b/browser/components/aboutlogins/tests/browser/browser_openExport.js
index 1a61510862..f4f7761259 100644
--- a/browser/components/aboutlogins/tests/browser/browser_openExport.js
+++ b/browser/components/aboutlogins/tests/browser/browser_openExport.js
@@ -8,9 +8,6 @@
* Test the export logins file picker appears.
*/
-let { OSKeyStore } = ChromeUtils.importESModule(
- "resource://gre/modules/OSKeyStore.sys.mjs"
-);
let { TelemetryTestUtils } = ChromeUtils.importESModule(
"resource://testing-common/TelemetryTestUtils.sys.mjs"
);
diff --git a/browser/components/aboutlogins/tests/browser/browser_openSite.js b/browser/components/aboutlogins/tests/browser/browser_openSite.js
index f33d57a8e4..c3fc8d5cd1 100644
--- a/browser/components/aboutlogins/tests/browser/browser_openSite.js
+++ b/browser/components/aboutlogins/tests/browser/browser_openSite.js
@@ -44,7 +44,10 @@ add_task(async function test_launch_login_item() {
gBrowser,
TEST_LOGIN1.origin + "/"
);
- let reauthObserved = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ let reauthObserved = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ reauthObserved = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
await SpecialPowers.spawn(browser, [], async () => {
let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
loginItem._editButton.click();
diff --git a/browser/components/aboutlogins/tests/browser/browser_osAuthDialog.js b/browser/components/aboutlogins/tests/browser/browser_osAuthDialog.js
index 9c2688cc77..21a5eeda12 100644
--- a/browser/components/aboutlogins/tests/browser/browser_osAuthDialog.js
+++ b/browser/components/aboutlogins/tests/browser/browser_osAuthDialog.js
@@ -1,12 +1,105 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
-add_task(async function test() {
- info(
- `updatechannel: ${UpdateUtils.getUpdateChannel(false)}; platform: ${
- AppConstants.platform
- }`
+"use strict";
+
+// On mac, this test times out in chaos mode
+requestLongerTimeout(2);
+
+const PAGE_PREFS = "about:preferences";
+const PAGE_PRIVACY = PAGE_PREFS + "#privacy";
+const SELECTORS = {
+ reauthCheckbox: "#osReauthCheckbox",
+};
+
+add_setup(async function () {
+ TEST_LOGIN1 = await addLogin(TEST_LOGIN1);
+ TEST_LOGIN2 = await addLogin(TEST_LOGIN2);
+ // Undo mocking from head.js
+ sinon.restore();
+});
+
+add_task(async function test_os_auth_enabled_with_checkbox() {
+ let finalPrefPaneLoaded = TestUtils.topicObserved("sync-pane-loaded");
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: PAGE_PRIVACY },
+ async function (browser) {
+ await finalPrefPaneLoaded;
+
+ await SpecialPowers.spawn(
+ browser,
+ [SELECTORS, AppConstants.NIGHTLY_BUILD],
+ async (selectors, isNightly) => {
+ is(
+ content.document.querySelector(selectors.reauthCheckbox).checked,
+ isNightly,
+ "OSReauth for Passwords should be checked"
+ );
+ }
+ );
+ is(
+ LoginHelper.getOSAuthEnabled(PASSWORDS_OS_REAUTH_PREF),
+ AppConstants.NIGHTLY_BUILD,
+ "OSAuth should be enabled."
+ );
+ }
);
+});
+
+add_task(async function test_os_auth_disabled_with_checkbox() {
+ let finalPrefPaneLoaded = TestUtils.topicObserved("sync-pane-loaded");
+ LoginHelper.setOSAuthEnabled(PASSWORDS_OS_REAUTH_PREF, false);
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: PAGE_PRIVACY },
+ async function (browser) {
+ await finalPrefPaneLoaded;
+
+ await SpecialPowers.spawn(browser, [SELECTORS], async selectors => {
+ is(
+ content.document.querySelector(selectors.reauthCheckbox).checked,
+ false,
+ "OSReauth for passwords should be unchecked"
+ );
+ });
+ is(
+ LoginHelper.getOSAuthEnabled(PASSWORDS_OS_REAUTH_PREF),
+ false,
+ "OSAuth should be disabled"
+ );
+ }
+ );
+ LoginHelper.setOSAuthEnabled(PASSWORDS_OS_REAUTH_PREF, true);
+});
+
+add_task(async function test_OSAuth_enabled_with_random_value_in_pref() {
+ let finalPrefPaneLoaded = TestUtils.topicObserved("sync-pane-loaded");
+ await SpecialPowers.pushPrefEnv({
+ set: [[PASSWORDS_OS_REAUTH_PREF, "poutine-gravy"]],
+ });
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: PAGE_PRIVACY },
+ async function (browser) {
+ await finalPrefPaneLoaded;
+ await SpecialPowers.spawn(browser, [SELECTORS], async selectors => {
+ let reauthCheckbox = content.document.querySelector(
+ selectors.reauthCheckbox
+ );
+ is(
+ reauthCheckbox.checked,
+ true,
+ "OSReauth for passwords should be checked"
+ );
+ });
+ is(
+ LoginHelper.getOSAuthEnabled(PASSWORDS_OS_REAUTH_PREF),
+ true,
+ "OSAuth should be enabled since the pref does not decrypt to 'opt out'."
+ );
+ }
+ );
+});
+
+add_task(async function test_osAuth_shown_on_edit_login() {
if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
Assert.ok(
true,
@@ -14,41 +107,51 @@ add_task(async function test() {
);
return;
}
-
- TEST_LOGIN1 = await addLogin(TEST_LOGIN1);
-
await BrowserTestUtils.openNewForegroundTab({
gBrowser,
url: "about:logins",
});
-
- registerCleanupFunction(function () {
- Services.logins.removeAllUserFacingLogins();
- BrowserTestUtils.removeTab(gBrowser.selectedTab);
- });
-
- // Show OS auth dialog when Reveal Password checkbox is checked if not on a new login
- let osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(false);
+ let osAuthDialogShown = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
let loginItem = content.document.querySelector("login-item");
- let revealCheckbox = loginItem.shadowRoot.querySelector(
- ".reveal-password-checkbox"
+ Assert.ok(
+ !loginItem.dataset.editing,
+ "Not in edit mode before clicking 'Edit'"
);
- revealCheckbox.click();
+ let editButton = loginItem.shadowRoot.querySelector("edit-button");
+ editButton.click();
});
+
await osAuthDialogShown;
- info("OS auth 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"
+ info("OS auth dialog shown and authenticated");
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
+ await ContentTaskUtils.waitForCondition(
+ () => content.document.querySelector("login-item").dataset.editing,
+ "login item should be in 'edit' mode"
);
+ });
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+add_task(async function test_osAuth_shown_on_reveal_password() {
+ if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
Assert.ok(
- !revealCheckbox.checked,
- "reveal checkbox should be unchecked if OS auth dialog canceled"
+ true,
+ `skipping test since oskeystore cannot be automated in this environment`
);
+ return;
+ }
+ await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ url: "about:logins",
});
- osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ let osAuthDialogShown = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
let loginItem = content.document.querySelector("login-item");
let revealCheckbox = loginItem.shadowRoot.querySelector(
@@ -68,10 +171,70 @@ add_task(async function test() {
"reveal checkbox should be checked if OS auth dialog authenticated"
);
});
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
- info("'Edit' shouldn't show the prompt since the user has authenticated now");
+add_task(async function test_osAuth_shown_on_copy_password() {
+ if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
+ Assert.ok(
+ true,
+ `skipping test since oskeystore cannot be automated in this environment`
+ );
+ return;
+ }
+ await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ url: "about:logins",
+ });
+ let osAuthDialogShown = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
let loginItem = content.document.querySelector("login-item");
+ let copyPassword = loginItem.shadowRoot.querySelector(
+ "copy-password-button"
+ );
+ copyPassword.click();
+ });
+ await osAuthDialogShown;
+ info("OS auth dialog shown and authenticated");
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
+ info("Password was copied to clipboard");
+ });
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+add_task(async function test_osAuth_not_shown_within_expiration_time() {
+ if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
+ Assert.ok(
+ true,
+ `skipping test since oskeystore cannot be automated in this environment`
+ );
+ return;
+ }
+ await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ url: "about:logins",
+ });
+ let osAuthDialogShown = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
+ let loginItem = content.document.querySelector("login-item");
+ let copyPassword = loginItem.shadowRoot.querySelector(
+ "copy-password-button"
+ );
+ copyPassword.click();
+ });
+ await osAuthDialogShown;
+ info("OS auth dialog shown and authenticated");
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
+ info(
+ "'Edit' shouldn't show the prompt since the user has authenticated now"
+ );
+ let loginItem = content.document.querySelector("login-item");
Assert.ok(
!loginItem.dataset.editing,
"Not in edit mode before clicking 'Edit'"
@@ -85,16 +248,43 @@ add_task(async function test() {
);
Assert.ok(loginItem.dataset.editing, "In edit mode");
});
-
- info("Test that the OS auth prompt is shown after about:logins is reopened");
BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+add_task(async function test_osAuth_shown_after_expiration_timeout() {
+ if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
+ Assert.ok(
+ true,
+ `skipping test since oskeystore cannot be automated in this environment`
+ );
+ return;
+ }
await BrowserTestUtils.openNewForegroundTab({
gBrowser,
url: "about:logins",
});
+ let osAuthDialogShown = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
+ let loginItem = content.document.querySelector("login-item");
+ let copyPassword = loginItem.shadowRoot.querySelector(
+ "copy-password-button"
+ );
+ copyPassword.click();
+ });
+ await osAuthDialogShown;
+ info("OS auth dialog shown and authenticated");
+
+ // Show OS auth dialog since the timeout will have expired
+
+ if (OSKeyStore.canReauth()) {
+ osAuthDialogShown = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
+ loginResult: true,
+ });
+ }
- // Show OS auth dialog since the page has been reloaded.
- osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(false);
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
let loginItem = content.document.querySelector("login-item");
let revealCheckbox = loginItem.shadowRoot.querySelector(
@@ -103,63 +293,91 @@ add_task(async function test() {
revealCheckbox.click();
});
await osAuthDialogShown;
- info("OS auth dialog shown and canceled");
+ info("OS auth dialog shown and authenticated");
+ await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
- // Show OS auth dialog since the previous attempt was canceled
- osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+add_task(async function test_osAuth_shown_on_reload() {
+ if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
+ Assert.ok(
+ true,
+ `skipping test since oskeystore cannot be automated in this environment`
+ );
+ return;
+ }
+ await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ url: "about:logins",
+ });
+ let osAuthDialogShown = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
let loginItem = content.document.querySelector("login-item");
- let revealCheckbox = loginItem.shadowRoot.querySelector(
- ".reveal-password-checkbox"
+ let copyPassword = loginItem.shadowRoot.querySelector(
+ "copy-password-button"
);
- revealCheckbox.click();
- info("clicking on reveal checkbox to hide the password");
- revealCheckbox.click();
+ copyPassword.click();
});
await osAuthDialogShown;
- info("OS auth dialog shown and passed");
+ info("OS auth dialog shown and authenticated");
- // Show OS auth dialog since the timeout will have expired
- osAuthDialogShown = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
- loginResult: true,
+ info("Test that the OS auth prompt is shown after about:logins is reopened");
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+ await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ url: "about:logins",
});
+
+ // Show OS auth dialog since the page has been reloaded.
+ osAuthDialogShown = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
let loginItem = content.document.querySelector("login-item");
let revealCheckbox = loginItem.shadowRoot.querySelector(
".reveal-password-checkbox"
);
- info("clicking on reveal checkbox to reveal password");
revealCheckbox.click();
});
- info("waiting for os auth dialog");
await osAuthDialogShown;
- info("OS auth dialog shown and passed after timeout expiration");
-
- // Disable the OS auth feature and confirm the prompt doesn't appear
- await SpecialPowers.pushPrefEnv({
- set: [["signon.management.page.os-auth.enabled", false]],
- });
- info("Reload about:logins to reset the timeout");
+ info("OS auth dialog shown and authenticated");
BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+add_task(async function test_osAuth_shown_again_on_cancel() {
+ if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
+ Assert.ok(
+ true,
+ `skipping test since oskeystore cannot be automated in this environment`
+ );
+ return;
+ }
await BrowserTestUtils.openNewForegroundTab({
gBrowser,
url: "about:logins",
});
-
- info("'Edit' shouldn't show the prompt since the feature has been disabled");
+ let osAuthDialogShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(false);
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
let loginItem = content.document.querySelector("login-item");
- Assert.ok(
- !loginItem.dataset.editing,
- "Not in edit mode before clicking 'Edit'"
+ let revealCheckbox = loginItem.shadowRoot.querySelector(
+ ".reveal-password-checkbox"
);
- let editButton = loginItem.shadowRoot.querySelector("edit-button");
- editButton.click();
-
- await ContentTaskUtils.waitForCondition(
- () => loginItem.dataset.editing,
- "waiting for 'edit' mode"
+ revealCheckbox.click();
+ });
+ await osAuthDialogShown;
+ info("OS auth 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 OS auth dialog canceled"
);
- Assert.ok(loginItem.dataset.editing, "In edit mode");
});
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
diff --git a/browser/components/aboutlogins/tests/browser/browser_removeAllDialog.js b/browser/components/aboutlogins/tests/browser/browser_removeAllDialog.js
index c5879ceeaf..bcd09ca9a2 100644
--- a/browser/components/aboutlogins/tests/browser/browser_removeAllDialog.js
+++ b/browser/components/aboutlogins/tests/browser/browser_removeAllDialog.js
@@ -2,8 +2,6 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-disable mozilla/no-arbitrary-setTimeout */
-const OS_REAUTH_PREF = "signon.management.page.os-auth.enabled";
-
async function openRemoveAllDialog(browser) {
await SimpleTest.promiseFocus(browser);
await BrowserTestUtils.synthesizeMouseAtCenter("menu-button", {}, browser);
@@ -80,9 +78,11 @@ async function waitForRemoveAllLogins() {
}
add_setup(async function () {
- await SpecialPowers.pushPrefEnv({
- set: [[OS_REAUTH_PREF, false]],
- });
+ // Undo mocking from head.js
+ sinon.restore();
+
+ let oldPrefValue = LoginHelper.getOSAuthEnabled(PASSWORDS_OS_REAUTH_PREF);
+ LoginHelper.setOSAuthEnabled(PASSWORDS_OS_REAUTH_PREF, false);
await BrowserTestUtils.openNewForegroundTab({
gBrowser,
url: "about:logins",
@@ -90,7 +90,7 @@ add_setup(async function () {
registerCleanupFunction(async () => {
BrowserTestUtils.removeTab(gBrowser.selectedTab);
Services.logins.removeAllUserFacingLogins();
- await SpecialPowers.popPrefEnv();
+ LoginHelper.setOSAuthEnabled(PASSWORDS_OS_REAUTH_PREF, oldPrefValue);
});
TEST_LOGIN1 = await addLogin(TEST_LOGIN1);
});
diff --git a/browser/components/aboutlogins/tests/browser/browser_tabKeyNav.js b/browser/components/aboutlogins/tests/browser/browser_tabKeyNav.js
index 890d39a316..6e2047e8e5 100644
--- a/browser/components/aboutlogins/tests/browser/browser_tabKeyNav.js
+++ b/browser/components/aboutlogins/tests/browser/browser_tabKeyNav.js
@@ -100,14 +100,6 @@ add_task(async function test_tab_key_nav() {
expectedSelector
);
- // By default, MacOS will skip over certain text controls, such as links.
- if (
- content.window.navigator.platform.toLowerCase().includes("mac") &&
- expectedElement.tagName === "A"
- ) {
- continue;
- }
-
const actualElement = getFocusedElement();
Assert.equal(
@@ -126,13 +118,6 @@ add_task(async function test_tab_key_nav() {
content.document,
expectedSelector
);
- // By default, MacOS will skip over certain text controls, such as links.
- if (
- content.window.navigator.platform.toLowerCase().includes("mac") &&
- expectedElement.tagName === "A"
- ) {
- continue;
- }
const actualElement = getFocusedElement();
Assert.equal(
diff --git a/browser/components/aboutlogins/tests/browser/browser_updateLogin.js b/browser/components/aboutlogins/tests/browser/browser_updateLogin.js
index 686b3951a1..192ff0270d 100644
--- a/browser/components/aboutlogins/tests/browser/browser_updateLogin.js
+++ b/browser/components/aboutlogins/tests/browser/browser_updateLogin.js
@@ -124,7 +124,10 @@ add_task(async function test_login_item() {
}
let browser = gBrowser.selectedBrowser;
- let reauthObserved = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ let reauthObserved = Promise.resolve();
+ if (OSKeyStore.canReauth()) {
+ reauthObserved = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
+ }
await SpecialPowers.spawn(
browser,
[LoginHelper.loginToVanillaObject(TEST_LOGIN1)],
@@ -163,9 +166,11 @@ add_task(async function test_login_item() {
],
test_discard_dialog
);
- reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
- loginResult: true,
- });
+ if (OSKeyStore.canReauth()) {
+ reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
+ loginResult: true,
+ });
+ }
await SpecialPowers.spawn(browser, [], async () => {
let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
let editButton = loginItem.shadowRoot
@@ -184,9 +189,11 @@ add_task(async function test_login_item() {
],
test_discard_dialog
);
- reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
- loginResult: true,
- });
+ if (OSKeyStore.canReauth()) {
+ reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
+ loginResult: true,
+ });
+ }
await SpecialPowers.spawn(browser, [], async () => {
let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
let editButton = loginItem.shadowRoot
@@ -289,9 +296,11 @@ add_task(async function test_login_item() {
);
}
);
- reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
- loginResult: true,
- });
+ if (OSKeyStore.canReauth()) {
+ reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
+ loginResult: true,
+ });
+ }
await SpecialPowers.spawn(browser, [], async () => {
let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
let editButton = loginItem.shadowRoot
@@ -360,9 +369,11 @@ add_task(async function test_login_item() {
"Password field width should be correctly updated"
);
});
- reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
- loginResult: true,
- });
+ if (OSKeyStore.canReauth()) {
+ reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
+ loginResult: true,
+ });
+ }
await SpecialPowers.spawn(browser, [], async () => {
let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
let editButton = loginItem.shadowRoot
diff --git a/browser/components/aboutlogins/tests/browser/head.js b/browser/components/aboutlogins/tests/browser/head.js
index 82d3cf2062..22ab7ef964 100644
--- a/browser/components/aboutlogins/tests/browser/head.js
+++ b/browser/components/aboutlogins/tests/browser/head.js
@@ -13,6 +13,24 @@ let { _AboutLogins } = ChromeUtils.importESModule(
let { OSKeyStoreTestUtils } = ChromeUtils.importESModule(
"resource://testing-common/OSKeyStoreTestUtils.sys.mjs"
);
+
+const { OSKeyStore } = ChromeUtils.importESModule(
+ "resource://gre/modules/OSKeyStore.sys.mjs"
+);
+
+let { sinon } = ChromeUtils.importESModule(
+ "resource://testing-common/Sinon.sys.mjs"
+);
+
+// Always pretend OS Auth is enabled in this dir.
+if (OSKeyStoreTestUtils.canTestOSKeyStoreLogin() && OSKeyStore.canReauth()) {
+ // Enable OS reauth so we can test it.
+ sinon.stub(LoginHelper, "getOSAuthEnabled").returns(true);
+ registerCleanupFunction(() => {
+ sinon.restore();
+ });
+}
+
var { LoginTestUtils } = ChromeUtils.importESModule(
"resource://testing-common/LoginTestUtils.sys.mjs"
);
@@ -53,6 +71,15 @@ let TEST_LOGIN3 = new nsLoginInfo(
);
TEST_LOGIN3.QueryInterface(Ci.nsILoginMetaInfo).timePasswordChanged = 123456;
+const PASSWORDS_OS_REAUTH_PREF = "signon.management.page.os-auth.optout";
+const CryptoErrors = {
+ USER_CANCELED_PASSWORD: "User canceled primary password entry",
+ ENCRYPTION_FAILURE: "Couldn't encrypt string",
+ INVALID_ARG_ENCRYPT: "Need at least one plaintext to encrypt",
+ INVALID_ARG_DECRYPT: "Need at least one ciphertext to decrypt",
+ DECRYPTION_FAILURE: "Couldn't decrypt string",
+};
+
async function addLogin(login) {
const result = await Services.logins.addLoginAsync(login);
registerCleanupFunction(() => {
@@ -153,6 +180,12 @@ add_setup(async function setup_head() {
// Ignore MarionetteEvents error (Bug 1730837, Bug 1710079).
return;
}
+ if (msg.errorMessage.includes(CryptoErrors.DECRYPTION_FAILURE)) {
+ // Ignore decyption errors, we want to test if decryption failed
+ // But we cannot use try / catch in the test to catch this for some reason
+ // Bug 1403081 and Bug 1877720
+ return;
+ }
Assert.ok(false, msg.message || msg.errorMessage);
});
diff --git a/browser/components/aboutlogins/tests/chrome/test_confirm_delete_dialog.html b/browser/components/aboutlogins/tests/chrome/test_confirm_delete_dialog.html
index 68a58aee4f..afbae0c310 100644
--- a/browser/components/aboutlogins/tests/chrome/test_confirm_delete_dialog.html
+++ b/browser/components/aboutlogins/tests/chrome/test_confirm_delete_dialog.html
@@ -24,6 +24,7 @@ Test the confirmation-dialog component
</pre>
<script>
/** Test the confirmation-dialog component **/
+let isWin = navigator.platform.includes("Win");
let options = {
title: "confirm-delete-dialog-title",
@@ -65,7 +66,7 @@ add_task(async function test_initial_focus() {
add_task(async function test_tab_focus() {
gConfirmationDialog.show(options);
ok(!gConfirmationDialog.hidden, "The dialog should be visible");
- sendKey("TAB");
+ synthesizeKey("VK_TAB", { shiftKey: !isWin });
is(gConfirmationDialog.shadowRoot.activeElement, cancelButton,
"After opening the dialog and tabbing once, the cancel button should be focused");
gConfirmationDialog.hide();
@@ -86,7 +87,7 @@ add_task(async function test_enter_key_to_cancel() {
add_task(async function test_enter_key_to_confirm() {
let showPromise = gConfirmationDialog.show(options);
ok(!gConfirmationDialog.hidden, "The dialog should be visible");
- sendKey("TAB");
+ synthesizeKey("VK_TAB", { shiftKey: !isWin });
sendKey("RETURN");
try {
await showPromise;