diff options
Diffstat (limited to 'browser/extensions/formautofill/test')
19 files changed, 475 insertions, 152 deletions
diff --git a/browser/extensions/formautofill/test/browser/address/browser.toml b/browser/extensions/formautofill/test/browser/address/browser.toml index 8b7f1ec760..e8c72ae1b1 100644 --- a/browser/extensions/formautofill/test/browser/address/browser.toml +++ b/browser/extensions/formautofill/test/browser/address/browser.toml @@ -38,6 +38,8 @@ support-files = [ ["browser_address_doorhanger_ui.js"] +["browser_address_doorhanger_ui_lines.js"] + ["browser_address_doorhanger_unsupported_region.js"] ["browser_address_telemetry.js"] diff --git a/browser/extensions/formautofill/test/browser/address/browser_address_doorhanger_ui_lines.js b/browser/extensions/formautofill/test/browser/address/browser_address_doorhanger_ui_lines.js new file mode 100644 index 0000000000..01e888a5f8 --- /dev/null +++ b/browser/extensions/formautofill/test/browser/address/browser_address_doorhanger_ui_lines.js @@ -0,0 +1,32 @@ +"use strict"; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + ["extensions.formautofill.addresses.capture.enabled", true], + ["extensions.formautofill.addresses.supported", "on"], + ], + }); +}); + +add_task( + async function test_address_line_displays_normalized_state_in_save_doorhanger() { + await BrowserTestUtils.withNewTab( + { gBrowser, url: ADDRESS_FORM_URL }, + async function (browser) { + await showAddressDoorhanger(browser, { + "#address-level1": "Nova Scotia", + "#address-level2": "Somerset", + "#country": "CA", + }); + + const p = getNotification().querySelector( + `.address-save-update-row-container p:first-child` + ); + is(p.textContent, "Somerset, NS"); + + await clickAddressDoorhangerButton(SECONDARY_BUTTON); + } + ); + } +); diff --git a/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js b/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js index 62797739fc..dec367d8e9 100644 --- a/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js +++ b/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js @@ -1,7 +1,7 @@ "use strict"; -const { FormAutofillUtils } = ChromeUtils.importESModule( - "resource://gre/modules/shared/FormAutofillUtils.sys.mjs" +const { FormAutofill } = ChromeUtils.importESModule( + "resource://autofill/FormAutofill.sys.mjs" ); ChromeUtils.defineESModuleGetters(this, { @@ -53,7 +53,12 @@ add_task(async function test_defaultCountry() { Region._setHomeRegion("XX", false); await testDialog(EDIT_ADDRESS_DIALOG_URL, win => { let doc = win.document; - is(doc.querySelector("#country").value, "", "Default country set to empty"); + const countries = [...FormAutofill.countries.keys()]; + is( + countries[0], + doc.querySelector("#country").value, + "Default country set to first option in the list" + ); doc.querySelector("#cancel").click(); }); Region._setHomeRegion("US", false); @@ -250,10 +255,9 @@ add_task(async function test_saveAddressCA() { "Postal Code", "CA postal-code label should be 'Postal Code'" ); - is( - doc.querySelector("#address-level3-container").style.display, - "none", - "CA address-level3 should be hidden" + ok( + !doc.querySelector("#address-level3-container"), + "CA address-level3 should not be rendered" ); // Input address info and verify move through form with tab keys @@ -313,15 +317,13 @@ add_task(async function test_saveAddressDE() { "Postal Code", "DE postal-code label should be 'Postal Code'" ); - is( - doc.querySelector("#address-level1-container").style.display, - "none", - "DE address-level1 should be hidden" + ok( + !doc.querySelector("#address-level1-container"), + "DE address-level1 should not be rendered" ); - is( - doc.querySelector("#address-level3-container").style.display, - "none", - "DE address-level3 should be hidden" + ok( + !doc.querySelector("#address-level3-container"), + "DE address-level3 should not be rendered" ); // Input address info and verify move through form with tab keys doc.querySelector("#name").focus(); @@ -434,57 +436,28 @@ add_task(async function test_saveAddressIE() { add_task(async function test_countryAndStateFieldLabels() { await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => { - let doc = win.document; - // Change country to verify labels - doc.querySelector("#country").focus(); - - let mutableLabels = [ - "postal-code-container", - "address-level1-container", - "address-level2-container", - "address-level3-container", - ].map(containerID => - doc.getElementById(containerID).querySelector(":scope > .label-text") - ); - + const doc = win.document; for (let countryOption of doc.querySelector("#country").options) { - if (countryOption.value == "") { - info("Skipping the empty country option"); - continue; - } - // Clear L10N textContent to not leave leftovers between country tests - for (let labelEl of mutableLabels) { + for (const labelEl of doc.querySelectorAll(".label-text")) { doc.l10n.setAttributes(labelEl, ""); labelEl.textContent = ""; } + // Change country to verify labels + doc.querySelector("#country").focus(); + info(`Selecting '${countryOption.label}' (${countryOption.value})`); EventUtils.synthesizeKey(countryOption.label, {}, win); - let l10nResolve; - let l10nReady = new Promise(resolve => { - l10nResolve = resolve; - }); - let verifyL10n = () => { - if (mutableLabels.every(labelEl => labelEl.textContent)) { - win.removeEventListener("MozAfterPaint", verifyL10n); - l10nResolve(); - } - }; - win.addEventListener("MozAfterPaint", verifyL10n); - await l10nReady; - - // Check that the labels were filled - for (let labelEl of mutableLabels) { - isnot( - labelEl.textContent, - "", - "Ensure textContent is non-empty for: " + countryOption.value - ); - } + await waitForFocusAndFormReady(win); + + const allLabelsHaveText = [...doc.querySelectorAll(".label-text")].every( + labelEl => labelEl.textContent + ); + + ok(allLabelsHaveText, "All labels are rendered and have text content"); - let stateOptions = doc.querySelector("#address-level1").options; /* eslint-disable max-len */ let expectedStateOptions = { BS: { @@ -510,22 +483,22 @@ add_task(async function test_countryAndStateFieldLabels() { /* eslint-enable max-len */ if (expectedStateOptions[countryOption.value]) { + const stateOptions = doc.querySelector("#address-level1").options; let { keys, names } = expectedStateOptions[countryOption.value]; is( stateOptions.length, - keys.length + 1, - "stateOptions should list all options plus a blank entry" + keys.length, + "stateOptions should have the same length as the expected options" ); - is(stateOptions[0].value, "", "First State option should be blank"); for (let i = 1; i < stateOptions.length; i++) { is( stateOptions[i].value, - keys[i - 1], + keys[i], "Each State should be listed in alphabetical name order (key)" ); is( stateOptions[i].text, - names[i - 1], + names[i], "Each State should be listed in alphabetical name order (name)" ); } @@ -539,14 +512,15 @@ add_task(async function test_countryAndStateFieldLabels() { }); add_task(async function test_hiddenFieldNotSaved() { - await testDialog(EDIT_ADDRESS_DIALOG_URL, win => { - let doc = win.document; + await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => { + const doc = win.document; doc.querySelector("#address-level2").focus(); EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level2"], {}, win); doc.querySelector("#address-level1").focus(); EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level1"], {}, win); doc.querySelector("#country").focus(); EventUtils.synthesizeKey("Germany", {}, win); + await waitForFocusAndFormReady(win); doc.querySelector("#save").focus(); EventUtils.synthesizeKey("VK_RETURN", {}, win); }); @@ -598,10 +572,11 @@ add_task(async function test_hiddenFieldRemovedWhenCountryChanged() { await testDialog( EDIT_ADDRESS_DIALOG_URL, - win => { - let doc = win.document; + async win => { + const doc = win.document; doc.querySelector("#country").focus(); EventUtils.synthesizeKey("Germany", {}, win); + await waitForFocusAndFormReady(win); win.document.querySelector("#save").click(); }, { @@ -628,63 +603,33 @@ add_task(async function test_hiddenFieldRemovedWhenCountryChanged() { add_task(async function test_countrySpecificFieldsGetRequiredness() { Region._setHomeRegion("RO", false); await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => { - let doc = win.document; + const doc = win.document; is( doc.querySelector("#country").value, "RO", "Default country set to Romania" ); let provinceField = doc.getElementById("address-level1"); - ok( - !provinceField.required, - "address-level1 should not be marked as required" - ); - ok(provinceField.disabled, "address-level1 should be marked as disabled"); - is( - provinceField.parentNode.style.display, - "none", - "address-level1 is hidden for Romania" - ); + ok(!provinceField, "address-level1 should not be rendered"); doc.querySelector("#country").focus(); EventUtils.synthesizeKey("United States", {}, win); + await waitForFocusAndFormReady(win); + const stateField = doc.getElementById("address-level1"); - await TestUtils.waitForCondition( - () => { - provinceField = doc.getElementById("address-level1"); - return provinceField.parentNode.style.display != "none"; - }, - "Wait for address-level1 to become visible", - 10 - ); - - ok(provinceField.required, "address-level1 should be marked as required"); - ok( - !provinceField.disabled, - "address-level1 should not be marked as disabled" - ); + ok(stateField.required, "address-level1 should be marked as required"); + ok(!stateField.disabled, "address-level1 should not be marked as disabled"); // Dispatch a dummy key event so that <select>'s incremental search is cleared. EventUtils.synthesizeKey("VK_ACCEPT", {}, win); - doc.querySelector("#country").focus(); EventUtils.synthesizeKey("Romania", {}, win); - await TestUtils.waitForCondition( - () => { - provinceField = doc.getElementById("address-level1"); - return provinceField.parentNode.style.display == "none"; - }, - "Wait for address-level1 to become hidden", - 10 - ); - + await waitForFocusAndFormReady(win); ok( - provinceField.required, - "address-level1 will still be marked as required" + !doc.getElementById("address-level1"), + "address-level1 is not rendered " ); - ok(provinceField.disabled, "address-level1 should be marked as disabled"); - doc.querySelector("#cancel").click(); }); }); diff --git a/browser/extensions/formautofill/test/browser/creditCard/browser.toml b/browser/extensions/formautofill/test/browser/creditCard/browser.toml index 580ce936d4..ead527488e 100644 --- a/browser/extensions/formautofill/test/browser/creditCard/browser.toml +++ b/browser/extensions/formautofill/test/browser/creditCard/browser.toml @@ -1,7 +1,6 @@ [DEFAULT] prefs = [ "extensions.formautofill.creditCards.enabled=true", - "extensions.formautofill.reauth.enabled=true", "toolkit.telemetry.ipcBatchTimeout=0", # lower the interval for event telemetry in the content process to update the parent process ] support-files = [ @@ -41,11 +40,13 @@ skip-if = [ ] ["browser_creditCard_doorhanger_display.js"] -skip-if = [ - "apple_catalina && !debug", # perma-fail see Bug 1655601 - "apple_silicon && !debug", # perma-fail see Bug 1655601 - "win11_2009 && ccov", # Bug 1655600 -] +skip-if = ["true"] # Bug 1895422 +# Bug 1895422 - Fix this test for linux then uncomment. +# skip-if = [ +# "apple_catalina && !debug", # perma-fail see Bug 1655601 +# "apple_silicon && !debug", # perma-fail see Bug 1655601 +# "win11_2009 && ccov", # Bug 1655600 +# ] ["browser_creditCard_doorhanger_fields.js"] skip-if = [ @@ -102,6 +103,9 @@ skip-if = ["apple_silicon && !debug"] # Bug 1714221 ["browser_creditCard_heuristics_cc_type.js"] skip-if = ["apple_silicon && !debug"] # Bug 1714221 +["browser_creditCard_osAuth.js"] +skip-if = ["os == 'linux'"] + ["browser_creditCard_submission_autodetect_type.js"] skip-if = ["apple_silicon && !debug"] diff --git a/browser/extensions/formautofill/test/browser/creditCard/browser_anti_clickjacking.js b/browser/extensions/formautofill/test/browser/creditCard/browser_anti_clickjacking.js index f7fc731e54..0398c6242d 100644 --- a/browser/extensions/formautofill/test/browser/creditCard/browser_anti_clickjacking.js +++ b/browser/extensions/formautofill/test/browser/creditCard/browser_anti_clickjacking.js @@ -16,6 +16,26 @@ add_task(async function setup_storage() { ); }); +async function disableOSAuthForThisTest() { + // Revert head.js change that mocks os auth + sinon.restore(); + + let oldValue = FormAutofillUtils.getOSAuthEnabled( + FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF + ); + FormAutofillUtils.setOSAuthEnabled( + FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF, + false + ); + + registerCleanupFunction(() => { + FormAutofillUtils.setOSAuthEnabled( + FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF, + oldValue + ); + }); +} + add_task(async function test_active_delay() { // This is a workaround for the fact that we don't have a way // to know when the popup was opened exactly and this makes our test @@ -26,11 +46,11 @@ add_task(async function test_active_delay() { // gets opened and listen for it in this test before we check if the item // is disabled. await SpecialPowers.pushPrefEnv({ - set: [ - ["security.notification_enable_delay", 1000], - ["extensions.formautofill.reauth.enabled", false], - ], + set: [["security.notification_enable_delay", 1000]], }); + + await disableOSAuthForThisTest(); + await BrowserTestUtils.withNewTab( { gBrowser, url: CC_URL }, async function (browser) { @@ -86,10 +106,7 @@ add_task(async function test_active_delay() { add_task(async function test_no_delay() { await SpecialPowers.pushPrefEnv({ - set: [ - ["security.notification_enable_delay", 1000], - ["extensions.formautofill.reauth.enabled", false], - ], + set: [["security.notification_enable_delay", 1000]], }); await BrowserTestUtils.withNewTab( { gBrowser, url: ADDRESS_URL }, diff --git a/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_action.js b/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_action.js index 82122925d7..b5a8019f0d 100644 --- a/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_action.js +++ b/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_action.js @@ -132,12 +132,14 @@ add_task(async function test_update_doorhanger_click_save() { await setStorage(TEST_CREDIT_CARD_1); let creditCards = await getCreditCards(); is(creditCards.length, 1, "1 credit card in storage"); + let osKeyStoreLoginShown = null; let onChanged = waitForStorageChangedEvents("add"); await BrowserTestUtils.withNewTab( { gBrowser, url: CREDITCARD_FORM_URL }, async function (browser) { - let osKeyStoreLoginShown = - OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + if (OSKeyStore.canReauth()) { + osKeyStoreLoginShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + } let onPopupShown = waitForPopupShown(); await openPopupOn(browser, "form #cc-name"); await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser); @@ -153,7 +155,10 @@ add_task(async function test_update_doorhanger_click_save() { await onPopupShown; await clickDoorhangerButton(SECONDARY_BUTTON); - await osKeyStoreLoginShown; + if (osKeyStoreLoginShown) { + await osKeyStoreLoginShown; + ok(osKeyStoreLoginShown, "OS re-auth promise Complete"); + } } ); await onChanged; diff --git a/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_display.js b/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_display.js index 715eceb3eb..8db32d9462 100644 --- a/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_display.js +++ b/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_display.js @@ -107,16 +107,20 @@ add_task(async function test_doorhanger_not_shown_when_autofill_untouched() { let creditCards = await getCreditCards(); is(creditCards.length, 1, "1 credit card in storage"); + let osKeyStoreLoginShown = null; let onUsed = waitForStorageChangedEvents("notifyUsed"); await BrowserTestUtils.withNewTab( { gBrowser, url: CREDITCARD_FORM_URL }, async function (browser) { - let osKeyStoreLoginShown = - OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + if (OSKeyStore.canReauth()) { + osKeyStoreLoginShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + } await openPopupOn(browser, "form #cc-name"); await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser); await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser); - await osKeyStoreLoginShown; + if (osKeyStoreLoginShown) { + await osKeyStoreLoginShown; + } await waitForAutofill(browser, "#cc-name", "John Doe"); await SpecialPowers.spawn(browser, [], async function () { @@ -186,12 +190,15 @@ add_task( await setStorage(TEST_CREDIT_CARD_1, TEST_CREDIT_CARD_2); let creditCards = await getCreditCards(); is(creditCards.length, 2, "2 credit card in storage"); + let osKeyStoreLoginShown = null; let onUsed = waitForStorageChangedEvents("notifyUsed"); await BrowserTestUtils.withNewTab( { gBrowser, url: CREDITCARD_FORM_URL }, async function (browser) { - let osKeyStoreLoginShown = - OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + if (OSKeyStore.canReauth()) { + osKeyStoreLoginShown = + OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + } await openPopupOn(browser, "form #cc-number"); await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser); await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser); @@ -214,7 +221,9 @@ add_task( await sleep(1000); is(PopupNotifications.panel.state, "closed", "Doorhanger is hidden"); - await osKeyStoreLoginShown; + if (osKeyStoreLoginShown) { + await osKeyStoreLoginShown; + } } ); await onUsed; @@ -242,12 +251,15 @@ add_task( let creditCards = await getCreditCards(); is(creditCards.length, 2, "2 credit card in storage"); + let osKeyStoreLoginShown = null; let onUsed = waitForStorageChangedEvents("notifyUsed"); await BrowserTestUtils.withNewTab( { gBrowser, url: CREDITCARD_FORM_URL }, async function (browser) { - let osKeyStoreLoginShown = - OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + if (OSKeyStore.canReauth()) { + osKeyStoreLoginShown = + OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + } await openPopupOn(browser, "form #cc-number"); await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser); await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser); @@ -267,7 +279,9 @@ add_task( await sleep(1000); is(PopupNotifications.panel.state, "closed", "Doorhanger is hidden"); - await osKeyStoreLoginShown; + if (osKeyStoreLoginShown) { + await osKeyStoreLoginShown; + } } ); await onUsed; diff --git a/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_fields.js b/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_fields.js index c1ebef737e..7ba8bfab91 100644 --- a/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_fields.js +++ b/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_fields.js @@ -13,18 +13,23 @@ add_task(async function test_update_autofill_name_field() { let creditCards = await getCreditCards(); is(creditCards.length, 1, "1 credit card in storage"); + let osKeyStoreLoginShown = null; let onChanged = waitForStorageChangedEvents("update", "notifyUsed"); await BrowserTestUtils.withNewTab( { gBrowser, url: CREDITCARD_FORM_URL }, async function (browser) { - let osKeyStoreLoginShown = - OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + if (OSKeyStore.canReauth()) { + osKeyStoreLoginShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + } let onPopupShown = waitForPopupShown(); await openPopupOn(browser, "form #cc-name"); await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser); await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser); - await osKeyStoreLoginShown; + if (osKeyStoreLoginShown) { + await osKeyStoreLoginShown; + ok(osKeyStoreLoginShown, "OS Auth Dialog shown and authenticated"); + } await waitForAutofill(browser, "#cc-name", "John Doe"); await focusUpdateSubmitForm(browser, { @@ -63,17 +68,22 @@ add_task(async function test_update_autofill_exp_date_field() { await setStorage(TEST_CREDIT_CARD_1); let creditCards = await getCreditCards(); is(creditCards.length, 1, "1 credit card in storage"); + let osKeyStoreLoginShown = null; let onChanged = waitForStorageChangedEvents("update", "notifyUsed"); await BrowserTestUtils.withNewTab( { gBrowser, url: CREDITCARD_FORM_URL }, async function (browser) { - let osKeyStoreLoginShown = - OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + if (OSKeyStore.canReauth()) { + osKeyStoreLoginShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + } let onPopupShown = waitForPopupShown(); await openPopupOn(browser, "form #cc-name"); await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser); await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser); - await osKeyStoreLoginShown; + if (osKeyStoreLoginShown) { + await osKeyStoreLoginShown; + ok(osKeyStoreLoginShown, "OS Auth Dialog shown and authenticated"); + } await waitForAutofill(browser, "#cc-name", "John Doe"); await focusUpdateSubmitForm(browser, { diff --git a/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_iframe.js b/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_iframe.js index 2781e5acf6..774c3d7b25 100644 --- a/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_iframe.js +++ b/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_doorhanger_iframe.js @@ -30,8 +30,10 @@ add_task(async function test_iframe_submit_untouched_creditCard_form() { await BrowserTestUtils.withNewTab( { gBrowser, url: CREDITCARD_FORM_IFRAME_URL }, async function (browser) { - let osKeyStoreLoginShown = - OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + let osKeyStoreLoginShown = Promise.resolve(); + if (OSKeyStore.canReauth()) { + osKeyStoreLoginShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + } let iframeBC = browser.browsingContext.children[0]; await openPopupOnSubframe(browser, iframeBC, "form #cc-name"); diff --git a/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_osAuth.js b/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_osAuth.js new file mode 100644 index 0000000000..0fe6e1e07c --- /dev/null +++ b/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_osAuth.js @@ -0,0 +1,200 @@ +"use strict"; + +const PAGE_PREFS = "about:preferences"; +const PAGE_PRIVACY = PAGE_PREFS + "#privacy"; +const SELECTORS = { + savedCreditCardsBtn: "#creditCardAutofill button", + reauthCheckbox: "#creditCardReauthenticate checkbox", +}; + +// On mac, this test times out in chaos mode +requestLongerTimeout(2); + +add_setup(async function () { + // Revert head.js change that mocks os auth + sinon.restore(); + + // Load in a few credit cards + await SpecialPowers.pushPrefEnv({ + set: [["privacy.reduceTimerPrecision", false]], + }); + await setStorage(TEST_CREDIT_CARD_1, TEST_CREDIT_CARD_2); +}); + +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 credit cards should be checked" + ); + } + ); + is( + FormAutofillUtils.getOSAuthEnabled( + FormAutofillUtils.AUTOFILL_CREDITCARDS_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"); + FormAutofillUtils.setOSAuthEnabled( + FormAutofillUtils.AUTOFILL_CREDITCARDS_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 credit cards should be unchecked" + ); + }); + is( + FormAutofillUtils.getOSAuthEnabled( + FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF + ), + false, + "OSAuth should be disabled" + ); + } + ); + FormAutofillUtils.setOSAuthEnabled( + FormAutofillUtils.AUTOFILL_CREDITCARDS_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: [ + [FormAutofillUtils.AUTOFILL_CREDITCARDS_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 credit cards should be checked" + ); + }); + is( + FormAutofillUtils.getOSAuthEnabled( + FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF + ), + true, + "OSAuth should be enabled since the pref does not decrypt to 'opt out'." + ); + } + ); +}); + +add_task(async function test_osAuth_enabled_behaviour() { + let finalPrefPaneLoaded = TestUtils.topicObserved("sync-pane-loaded"); + await SpecialPowers.pushPrefEnv({ + set: [[FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF, ""]], + }); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: PAGE_PRIVACY }, + async function (browser) { + await finalPrefPaneLoaded; + if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) { + // The rest of the test uses Edit mode which causes an OS prompt in official builds. + return; + } + let reauthObserved = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + await SpecialPowers.spawn(browser, [SELECTORS], async selectors => { + content.document.querySelector(selectors.savedCreditCardsBtn).click(); + }); + let ccManageDialog = await waitForSubDialogLoad( + content, + MANAGE_CREDIT_CARDS_DIALOG_URL + ); + await SpecialPowers.spawn(ccManageDialog, [], async () => { + let selRecords = content.document.getElementById("credit-cards"); + await EventUtils.synthesizeMouseAtCenter( + selRecords.children[0], + [], + content + ); + content.document.querySelector("#edit").click(); + }); + await reauthObserved; // If the OS does not popup, this will cause a timeout in the test. + await waitForSubDialogLoad(content, EDIT_CREDIT_CARD_DIALOG_URL); + } + ); +}); + +add_task(async function test_osAuth_disabled_behavior() { + let finalPrefPaneLoaded = TestUtils.topicObserved("sync-pane-loaded"); + FormAutofillUtils.setOSAuthEnabled( + FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF, + false + ); + await BrowserTestUtils.withNewTab( + { gBrowser, url: PAGE_PRIVACY }, + async function (browser) { + await finalPrefPaneLoaded; + await SpecialPowers.spawn( + browser, + [SELECTORS.savedCreditCardsBtn, SELECTORS.reauthCheckbox], + async (saveButton, reauthCheckbox) => { + is( + content.document.querySelector(reauthCheckbox).checked, + false, + "OSReauth for credit cards should NOT be checked" + ); + content.document.querySelector(saveButton).click(); + } + ); + let ccManageDialog = await waitForSubDialogLoad( + content, + MANAGE_CREDIT_CARDS_DIALOG_URL + ); + await SpecialPowers.spawn(ccManageDialog, [], async () => { + let selRecords = content.document.getElementById("credit-cards"); + await EventUtils.synthesizeMouseAtCenter( + selRecords.children[0], + [], + content + ); + content.document.getElementById("edit").click(); + }); + info("The OS Auth dialog should NOT show up"); + // If OSAuth prompt shows up, the next line would cause a timeout since the edit dialog would not show up. + await waitForSubDialogLoad(content, EDIT_CREDIT_CARD_DIALOG_URL); + } + ); + FormAutofillUtils.setOSAuthEnabled( + FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF, + true + ); +}); diff --git a/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_telemetry.js b/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_telemetry.js index 7a4bff1e45..ea455df12a 100644 --- a/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_telemetry.js +++ b/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_telemetry.js @@ -154,12 +154,15 @@ async function openTabAndUseCreditCard( creditCard, { closeTab = true, submitForm = true } = {} ) { - let osKeyStoreLoginShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + let osKeyStoreLoginShown = null; let tab = await BrowserTestUtils.openNewForegroundTab( gBrowser, CREDITCARD_FORM_URL ); + if (OSKeyStore.canReauth()) { + osKeyStoreLoginShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + } let browser = tab.linkedBrowser; await openPopupOn(browser, "form #cc-name"); @@ -167,7 +170,9 @@ async function openTabAndUseCreditCard( await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser); } await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser); - await osKeyStoreLoginShown; + if (osKeyStoreLoginShown) { + await osKeyStoreLoginShown; + } await waitForAutofill(browser, "#cc-number", creditCard["cc-number"]); await focusUpdateSubmitForm( browser, @@ -692,10 +697,14 @@ add_task(async function test_submit_creditCard_update() { let creditCards = await getCreditCards(); Assert.equal(creditCards.length, 1, "1 credit card in storage"); - let osKeyStoreLoginShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + let osKeyStoreLoginShown = null; await BrowserTestUtils.withNewTab( { gBrowser, url: CREDITCARD_FORM_URL }, async function (browser) { + if (OSKeyStore.canReauth()) { + osKeyStoreLoginShown = + OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true); + } let onPopupShown = waitForPopupShown(); let onChanged; if (expectChanged !== undefined) { @@ -705,7 +714,9 @@ add_task(async function test_submit_creditCard_update() { await openPopupOn(browser, "form #cc-name"); await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser); await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser); - await osKeyStoreLoginShown; + if (osKeyStoreLoginShown) { + await osKeyStoreLoginShown; + } await waitForAutofill(browser, "#cc-name", "John Doe"); await focusUpdateSubmitForm(browser, { diff --git a/browser/extensions/formautofill/test/browser/head.js b/browser/extensions/formautofill/test/browser/head.js index 3f87f7b5ef..d82ed5076e 100644 --- a/browser/extensions/formautofill/test/browser/head.js +++ b/browser/extensions/formautofill/test/browser/head.js @@ -1,5 +1,9 @@ "use strict"; +const { ManageAddresses } = ChromeUtils.importESModule( + "chrome://formautofill/content/manageDialog.mjs" +); + const { OSKeyStore } = ChromeUtils.importESModule( "resource://gre/modules/OSKeyStore.sys.mjs" ); @@ -20,6 +24,27 @@ const { FormAutofillNameUtils } = ChromeUtils.importESModule( "resource://gre/modules/shared/FormAutofillNameUtils.sys.mjs" ); +const { FormAutofillUtils } = ChromeUtils.importESModule( + "resource://gre/modules/shared/FormAutofillUtils.sys.mjs" +); + +let { sinon } = ChromeUtils.importESModule( + "resource://testing-common/Sinon.sys.mjs" +); + +// Always pretend OS Auth is enabled in this dir. +if ( + gTestPath.includes("browser/creditCard") && + OSKeyStoreTestUtils.canTestOSKeyStoreLogin() && + OSKeyStore.canReauth() +) { + info("Stubbing out getOSAuthEnabled so it always returns true"); + sinon.stub(FormAutofillUtils, "getOSAuthEnabled").returns(true); + registerCleanupFunction(() => { + sinon.restore(); + }); +} + const MANAGE_ADDRESSES_DIALOG_URL = "chrome://formautofill/content/manageAddresses.xhtml"; const MANAGE_CREDIT_CARDS_DIALOG_URL = @@ -822,7 +847,7 @@ async function removeAllRecords() { async function waitForFocusAndFormReady(win) { return Promise.all([ new Promise(resolve => waitForFocus(resolve, win)), - BrowserTestUtils.waitForEvent(win, "FormReady"), + BrowserTestUtils.waitForEvent(win, "FormReadyForTests"), ]); } @@ -855,9 +880,12 @@ async function testDialog(url, testFn, arg = undefined) { "cc-number": await OSKeyStore.decrypt(arg.record["cc-number-encrypted"]), }); } - let win = window.openDialog(url, null, "width=600,height=600", arg); + const win = window.openDialog(url, null, "width=600,height=600", { + ...arg, + l10nStrings: ManageAddresses.getAddressL10nStrings(), + }); await waitForFocusAndFormReady(win); - let unloadPromise = BrowserTestUtils.waitForEvent(win, "unload"); + const unloadPromise = BrowserTestUtils.waitForEvent(win, "unload"); await testFn(win); return unloadPromise; } diff --git a/browser/extensions/formautofill/test/mochitest/creditCard/mochitest.toml b/browser/extensions/formautofill/test/mochitest/creditCard/mochitest.toml index ffd504bb45..0d6ea02569 100644 --- a/browser/extensions/formautofill/test/mochitest/creditCard/mochitest.toml +++ b/browser/extensions/formautofill/test/mochitest/creditCard/mochitest.toml @@ -2,7 +2,6 @@ prefs = [ "extensions.formautofill.creditCards.supported=on", "extensions.formautofill.creditCards.enabled=true", - "extensions.formautofill.reauth.enabled=true", ] support-files = [ "!/toolkit/components/satchel/test/satchel_common.js", diff --git a/browser/extensions/formautofill/test/mochitest/creditCard/test_basic_creditcard_autocomplete_form.html b/browser/extensions/formautofill/test/mochitest/creditCard/test_basic_creditcard_autocomplete_form.html index 717d40946f..9fad869629 100644 --- a/browser/extensions/formautofill/test/mochitest/creditCard/test_basic_creditcard_autocomplete_form.html +++ b/browser/extensions/formautofill/test/mochitest/creditCard/test_basic_creditcard_autocomplete_form.html @@ -197,10 +197,15 @@ add_task(async function check_fields_after_form_autofill() { }))); synthesizeKey("KEY_ArrowDown"); - let osKeyStoreLoginShown = waitForOSKeyStoreLogin(true); + let osKeyStoreLoginShown = Promise.resolve(); + if(OSKeyStore.canReauth()) { + osKeyStoreLoginShown = waitForOSKeyStoreLogin(true); + } await new Promise(resolve => SimpleTest.executeSoon(resolve)); await triggerAutofillAndCheckProfile(MOCK_STORAGE[1].cc); await osKeyStoreLoginShown; + // Enforcing this since it is unable to change back in chaos mode. + SpecialPowers.clearUserPref("toolkit.osKeyStore.unofficialBuildOnlyLogin"); }); // Fallback to history search after autofill values (for non-empty fields). diff --git a/browser/extensions/formautofill/test/mochitest/creditCard/test_clear_form.html b/browser/extensions/formautofill/test/mochitest/creditCard/test_clear_form.html index a1a3322c4e..4803151aae 100644 --- a/browser/extensions/formautofill/test/mochitest/creditCard/test_clear_form.html +++ b/browser/extensions/formautofill/test/mochitest/creditCard/test_clear_form.html @@ -124,6 +124,11 @@ add_task(async function simple_clear() { await triggerPopupAndHoverItem("#tel", 0); await confirmClear("#tel"); await checkIsFormCleared(); + + // Ensure the correctness of the autocomplete popup after the form is cleared + synthesizeKey("KEY_ArrowDown"); + await expectPopup(); + is(4, getMenuEntries().length, `Checking length of expected menu`); }); add_task(async function clear_adapted_record() { @@ -154,7 +159,10 @@ add_task(async function clear_distinct_section() { document.getElementById("form1").reset(); await triggerPopupAndHoverItem("#cc-name", 0); - let osKeyStoreLoginShown = waitForOSKeyStoreLogin(true); + let osKeyStoreLoginShown = Promise.resolve(); + if(OSKeyStore.canReauth()) { + osKeyStoreLoginShown = waitForOSKeyStoreLogin(true); + } await triggerAutofillAndCheckProfile(MOCK_CC_STORAGE_EXPECTED_FILL[0]); await osKeyStoreLoginShown; @@ -175,6 +183,8 @@ add_task(async function clear_distinct_section() { await triggerPopupAndHoverItem("#cc-name", 0); await confirmClear("#cc-name"); await checkIsFormCleared(); + // Enforcing this since it is unable to change back in chaos mode. + SpecialPowers.clearUserPref("toolkit.osKeyStore.unofficialBuildOnlyLogin"); }); </script> diff --git a/browser/extensions/formautofill/test/mochitest/creditCard/test_clear_form_expiry_select_elements.html b/browser/extensions/formautofill/test/mochitest/creditCard/test_clear_form_expiry_select_elements.html index 6ebef3bba1..f054bc5871 100644 --- a/browser/extensions/formautofill/test/mochitest/creditCard/test_clear_form_expiry_select_elements.html +++ b/browser/extensions/formautofill/test/mochitest/creditCard/test_clear_form_expiry_select_elements.html @@ -127,7 +127,10 @@ add_task(async function clear_distinct_section() { todo(false, "Cannot test OS key store login on official builds."); return; } - let osKeyStoreLoginShown = waitForOSKeyStoreLogin(true); + let osKeyStoreLoginShown = Promise.resolve(); + if(OSKeyStore.canReauth()) { + osKeyStoreLoginShown = waitForOSKeyStoreLogin(true); + } await triggerPopupAndHoverItem("#cc-name", 0); await triggerAutofillAndCheckProfile(MOCK_CC_STORAGE[0]); await osKeyStoreLoginShown; @@ -147,6 +150,8 @@ add_task(async function clear_distinct_section() { "cc-exp-month": "MM", "cc-exp-year": "YY" }); + // Enforcing this since it is unable to change back in chaos mode. + SpecialPowers.clearUserPref("toolkit.osKeyStore.unofficialBuildOnlyLogin"); }); </script> diff --git a/browser/extensions/formautofill/test/mochitest/creditCard/test_preview_highlight_with_multiple_cc_number_fields.html b/browser/extensions/formautofill/test/mochitest/creditCard/test_preview_highlight_with_multiple_cc_number_fields.html index a6d0572ac6..6b317f2392 100644 --- a/browser/extensions/formautofill/test/mochitest/creditCard/test_preview_highlight_with_multiple_cc_number_fields.html +++ b/browser/extensions/formautofill/test/mochitest/creditCard/test_preview_highlight_with_multiple_cc_number_fields.html @@ -143,7 +143,11 @@ add_task(async function check_filled_highlight() { return; } await triggerPopupAndHoverItem("#cc-name", 0); - let osKeyStoreLoginShown = waitForOSKeyStoreLogin(true); + let osKeyStoreLoginShown = Promise.resolve(); + +if (OSKeyStore.canReauth()) { + osKeyStoreLoginShown = waitForOSKeyStoreLogin(true); +} // filled 1st credit card option synthesizeKey("KEY_Enter"); await osKeyStoreLoginShown; @@ -151,6 +155,8 @@ add_task(async function check_filled_highlight() { let profile = MOCK_STORAGE_EXPECTED_FILL[0]; await setupListeners(elements, profile); await checkMultipleCCNumberFormStyle(profile, false); + // Enforcing this since it is unable to change back in chaos mode. + SpecialPowers.clearUserPref("toolkit.osKeyStore.unofficialBuildOnlyLogin"); }); </script> <p id="display"></p> diff --git a/browser/extensions/formautofill/test/mochitest/creditCard/test_preview_highlight_with_site_prefill.html b/browser/extensions/formautofill/test/mochitest/creditCard/test_preview_highlight_with_site_prefill.html index 090eb9290e..5517153f1a 100644 --- a/browser/extensions/formautofill/test/mochitest/creditCard/test_preview_highlight_with_site_prefill.html +++ b/browser/extensions/formautofill/test/mochitest/creditCard/test_preview_highlight_with_site_prefill.html @@ -87,11 +87,17 @@ add_task(async function check_filled_highlight() { return; } await triggerPopupAndHoverItem("#cc-number", 0); - let osKeyStoreLoginShown = waitForOSKeyStoreLogin(true); + + let osKeyStoreLoginShown = Promise.resolve(); + if(OSKeyStore.canReauth()) { + osKeyStoreLoginShown = waitForOSKeyStoreLogin(true); + } // filled 1st credit card option await triggerAutofillAndCheckProfile(MOCK_STORAGE_EXPECTED_FILL[0]); await osKeyStoreLoginShown; await checkFormFieldsStyle(MOCK_STORAGE_EXPECTED_FILL[0], false); + // Enforcing this since it is unable to change back in chaos mode. + SpecialPowers.clearUserPref("toolkit.osKeyStore.unofficialBuildOnlyLogin"); }); </script> <p id="display"></p> diff --git a/browser/extensions/formautofill/test/mochitest/formautofill_common.js b/browser/extensions/formautofill/test/mochitest/formautofill_common.js index 0e371ba3af..dab2d58b4a 100644 --- a/browser/extensions/formautofill/test/mochitest/formautofill_common.js +++ b/browser/extensions/formautofill/test/mochitest/formautofill_common.js @@ -2,6 +2,10 @@ /* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/EventUtils.js */ /* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */ /* eslint-disable no-unused-vars */ +// Despite a use of `spawnChrome` and thus ChromeUtils, we can't use isInstance +// here as it gets used in plain mochitests which don't have the ChromeOnly +// APIs for it. +/* eslint-disable mozilla/use-isInstance */ "use strict"; @@ -14,6 +18,10 @@ const { FormAutofillUtils } = SpecialPowers.ChromeUtils.importESModule( "resource://gre/modules/shared/FormAutofillUtils.sys.mjs" ); +const { OSKeyStore } = SpecialPowers.ChromeUtils.importESModule( + "resource://gre/modules/OSKeyStore.sys.mjs" +); + async function sleep(ms = 500, reason = "Intentionally wait for UI ready") { SimpleTest.requestFlakyTimeout(reason); await new Promise(resolve => setTimeout(resolve, ms)); @@ -353,7 +361,21 @@ async function canTestOSKeyStoreLogin() { } async function waitForOSKeyStoreLogin(login = false) { - await invokeAsyncChromeTask("FormAutofillTest:OSKeyStoreLogin", { login }); + // Need to fetch this from the parent in order for it to be correct. + let isOSAuthEnabled = await SpecialPowers.spawnChrome([], () => { + // Need to re-import this because we're running in the parent. + // eslint-disable-next-line no-shadow + const { FormAutofillUtils } = ChromeUtils.importESModule( + "resource://gre/modules/shared/FormAutofillUtils.sys.mjs" + ); + + return FormAutofillUtils.getOSAuthEnabled( + FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF + ); + }); + if (isOSAuthEnabled) { + await invokeAsyncChromeTask("FormAutofillTest:OSKeyStoreLogin", { login }); + } } function patchRecordCCNumber(record) { |