/** * Test LoginManagerParent.doAutocompleteSearch() */ "use strict"; const { sinon } = ChromeUtils.importESModule( "resource://testing-common/Sinon.sys.mjs" ); const { LoginManagerParent } = ChromeUtils.importESModule( "resource://gre/modules/LoginManagerParent.sys.mjs" ); // new-password to the happy path const NEW_PASSWORD_TEMPLATE_ARG = { actionOrigin: "https://mozilla.org", searchString: "", previousResult: null, requestId: "foo", hasBeenTypePassword: true, isSecure: true, isProbablyANewPasswordField: true, }; add_setup(async () => { Services.prefs.setBoolPref("signon.generation.available", true); Services.prefs.setBoolPref("signon.generation.enabled", true); await LoginTestUtils.remoteSettings.setupImprovedPasswordRules(); sinon .stub(LoginManagerParent._browsingContextGlobal, "get") .withArgs(123) .callsFake(() => { return { currentWindowGlobal: { documentPrincipal: Services.scriptSecurityManager.createContentPrincipalFromOrigin( "https://www.example.com^userContextId=1" ), documentURI: Services.io.newURI("https://www.example.com"), }, }; }); }); add_task(async function test_generated_noLogins() { let LMP = new LoginManagerParent(); LMP.useBrowsingContext(123); Assert.ok(LMP.doAutocompleteSearch, "doAutocompleteSearch exists"); let result1 = await LMP.doAutocompleteSearch( "https://example.com", NEW_PASSWORD_TEMPLATE_ARG ); equal(result1.logins.length, 0, "no logins"); Assert.ok(result1.generatedPassword, "has a generated password"); equal(result1.generatedPassword.length, 15, "generated password length"); Assert.ok( result1.willAutoSaveGeneratedPassword, "will auto-save when storage is empty" ); info("repeat the search and ensure the same password was used"); let result2 = await LMP.doAutocompleteSearch( "https://example.com", NEW_PASSWORD_TEMPLATE_ARG ); equal(result2.logins.length, 0, "no logins"); equal( result2.generatedPassword, result1.generatedPassword, "same generated password" ); Assert.ok( result1.willAutoSaveGeneratedPassword, "will auto-save when storage is still empty" ); info("Check cases where a password shouldn't be generated"); let result3 = await LMP.doAutocompleteSearch("https://example.com", { ...NEW_PASSWORD_TEMPLATE_ARG, ...{ hasBeenTypePassword: false, isProbablyANewPasswordField: false, }, }); equal( result3.generatedPassword, null, "no generated password when not a pw. field" ); let result4 = await LMP.doAutocompleteSearch("https://example.com", { ...NEW_PASSWORD_TEMPLATE_ARG, ...{ // This is false when there is no autocomplete="new-password" attribute && // LoginAutoComplete.isProbablyANewPasswordField returns false isProbablyANewPasswordField: false, }, }); equal( result4.generatedPassword, null, "no generated password when isProbablyANewPasswordField is false" ); LMP.useBrowsingContext(999); let result5 = await LMP.doAutocompleteSearch("https://example.com", { ...NEW_PASSWORD_TEMPLATE_ARG, }); equal( result5.generatedPassword, null, "no generated password with a missing browsingContextId" ); }); add_task(async function test_generated_emptyUsernameSavedLogin() { info("Test with a login that will prevent auto-saving"); await LoginTestUtils.addLogin({ username: "", password: "my-saved-password", origin: "https://example.com", formActionOrigin: NEW_PASSWORD_TEMPLATE_ARG.actionOrigin, }); let LMP = new LoginManagerParent(); LMP.useBrowsingContext(123); Assert.ok(LMP.doAutocompleteSearch, "doAutocompleteSearch exists"); let result1 = await LMP.doAutocompleteSearch( "https://example.com", NEW_PASSWORD_TEMPLATE_ARG ); equal(result1.logins.length, 1, "1 login"); Assert.ok(result1.generatedPassword, "has a generated password"); equal(result1.generatedPassword.length, 15, "generated password length"); Assert.ok( !result1.willAutoSaveGeneratedPassword, "won't auto-save when an empty-username match is found" ); LoginTestUtils.clearData(); });