From bae69b418ae8a89301dda95c10e00d9b4d09ee04 Mon Sep 17 00:00:00 2001 From: Matthew Noorenberghe Date: Mon, 20 May 2019 19:55:15 +0000 Subject: [PATCH] Bug 1548381 - LoginManagerParent.doAutocompleteSearch/getGeneratedPassword tests. r=sfoster Differential Revision: https://phabricator.services.mozilla.com/D31207 --HG-- extra : moz-landing-system : lando --- .../passwordmgr/LoginManagerParent.jsm | 7 ++ ...LoginManagerParent_doAutocompleteSearch.js | 92 +++++++++++++++++++ ...LoginManagerParent_getGeneratedPassword.js | 69 ++++++++++++++ .../passwordmgr/test/unit/xpcshell.ini | 2 + 4 files changed, 170 insertions(+) create mode 100644 toolkit/components/passwordmgr/test/unit/test_LoginManagerParent_doAutocompleteSearch.js create mode 100644 toolkit/components/passwordmgr/test/unit/test_LoginManagerParent_getGeneratedPassword.js diff --git a/toolkit/components/passwordmgr/LoginManagerParent.jsm b/toolkit/components/passwordmgr/LoginManagerParent.jsm index 6d3bc7ad0659..a72169237682 100644 --- a/toolkit/components/passwordmgr/LoginManagerParent.jsm +++ b/toolkit/components/passwordmgr/LoginManagerParent.jsm @@ -328,6 +328,13 @@ var LoginManagerParent = { }); }, + /** + * Expose `BrowsingContext` so we can stub it in tests. + */ + get _browsingContextGlobal() { + return BrowsingContext; + }, + getGeneratedPassword(browsingContextId) { if (!LoginHelper.enabled || !LoginHelper.generationAvailable || !LoginHelper.generationEnabled) { return null; diff --git a/toolkit/components/passwordmgr/test/unit/test_LoginManagerParent_doAutocompleteSearch.js b/toolkit/components/passwordmgr/test/unit/test_LoginManagerParent_doAutocompleteSearch.js new file mode 100644 index 000000000000..5d8586133ccb --- /dev/null +++ b/toolkit/components/passwordmgr/test/unit/test_LoginManagerParent_doAutocompleteSearch.js @@ -0,0 +1,92 @@ +/** + * Test LoginManagerParent.doAutocompleteSearch() + */ + +"use strict"; + +const {sinon} = ChromeUtils.import("resource://testing-common/Sinon.jsm"); +const {LoginManagerParent: LMP} = ChromeUtils.import("resource://gre/modules/LoginManagerParent.jsm"); + +add_task(async function test_doAutocompleteSearch_generated_noLogins() { + Services.prefs.setBoolPref("signon.generation.available", true); // TODO: test both with false + Services.prefs.setBoolPref("signon.generation.enabled", true); + + ok(LMP.doAutocompleteSearch, "doAutocompleteSearch exists"); + + // Default to the happy path + let arg1 = { + autocompleteInfo: { + section: "", + addressType: "", + contactType: "", + fieldName: "new-password", + canAutomaticallyPersist: false, + }, + browsingContextId: 123, + formOrigin: "https://example.com", + actionOrigin: "https://mozilla.org", + searchString: "", + previousResult: null, + requestId: "foo", + isSecure: true, + isPasswordField: true, + }; + + let sendMessageStub = sinon.stub(); + let fakeBrowser = { + messageManager: { + sendAsyncMessage: sendMessageStub, + }, + }; + + sinon.stub(LMP._browsingContextGlobal, "get").withArgs(123).callsFake(() => { + return { + currentWindowGlobal: { + documentPrincipal: Services.scriptSecurityManager.createCodebasePrincipalFromOrigin("https://www.example.com^userContextId=1"), + }, + }; + }); + + LMP.doAutocompleteSearch(arg1, fakeBrowser); + ok(sendMessageStub.calledOnce, "sendAsyncMessage was called"); + let msg1 = sendMessageStub.firstCall.args[1]; + equal(msg1.requestId, arg1.requestId, "requestId matches"); + equal(msg1.logins.length, 0, "no logins"); + ok(msg1.generatedPassword, "has a generated password"); + equal(msg1.generatedPassword.length, 15, "generated password length"); + sendMessageStub.resetHistory(); + + info("repeat the search and ensure the same password was used"); + LMP.doAutocompleteSearch(arg1, fakeBrowser); + ok(sendMessageStub.calledOnce, "sendAsyncMessage was called"); + let msg2 = sendMessageStub.firstCall.args[1]; + equal(msg2.requestId, arg1.requestId, "requestId matches"); + equal(msg2.logins.length, 0, "no logins"); + equal(msg2.generatedPassword, msg1.generatedPassword, "same generated password"); + sendMessageStub.resetHistory(); + + info("Check cases where a password shouldn't be generated"); + + LMP.doAutocompleteSearch({...arg1, ...{isPasswordField: false}}, fakeBrowser); + ok(sendMessageStub.calledOnce, "sendAsyncMessage was called"); + let msg = sendMessageStub.firstCall.args[1]; + equal(msg.requestId, arg1.requestId, "requestId matches"); + equal(msg.generatedPassword, null, "no generated password when not a pw. field"); + sendMessageStub.resetHistory(); + + let arg1_2 = {...arg1}; + arg1_2.autocompleteInfo.fieldName = ""; + LMP.doAutocompleteSearch(arg1_2, fakeBrowser); + ok(sendMessageStub.calledOnce, "sendAsyncMessage was called"); + msg = sendMessageStub.firstCall.args[1]; + equal(msg.requestId, arg1.requestId, "requestId matches"); + equal(msg.generatedPassword, null, "no generated password when not autocomplete=new-password"); + sendMessageStub.resetHistory(); + + LMP.doAutocompleteSearch({...arg1, ...{browsingContextId: 999}}, fakeBrowser); + ok(sendMessageStub.calledOnce, "sendAsyncMessage was called"); + msg = sendMessageStub.firstCall.args[1]; + equal(msg.requestId, arg1.requestId, "requestId matches"); + equal(msg.generatedPassword, null, "no generated password with a missing browsingContextId"); + sendMessageStub.resetHistory(); +}); diff --git a/toolkit/components/passwordmgr/test/unit/test_LoginManagerParent_getGeneratedPassword.js b/toolkit/components/passwordmgr/test/unit/test_LoginManagerParent_getGeneratedPassword.js new file mode 100644 index 000000000000..9be1ffb75ca7 --- /dev/null +++ b/toolkit/components/passwordmgr/test/unit/test_LoginManagerParent_getGeneratedPassword.js @@ -0,0 +1,69 @@ +/** + * Test LoginManagerParent.getGeneratedPassword() + */ + +"use strict"; + +const {sinon} = ChromeUtils.import("resource://testing-common/Sinon.jsm"); +const {LoginManagerParent: LMP} = ChromeUtils.import("resource://gre/modules/LoginManagerParent.jsm"); + +add_task(async function test_getGeneratedPassword() { + // Force the feature to be enabled. + Services.prefs.setBoolPref("signon.generation.available", true); + Services.prefs.setBoolPref("signon.generation.enabled", true); + + ok(LMP.getGeneratedPassword, "LMP.getGeneratedPassword exists"); + equal(LMP._generatedPasswordsByPrincipalOrigin.size, 0, "Empty cache to start"); + + equal(LMP.getGeneratedPassword(99), null, "Null with no BrowsingContext"); + + ok(LMP._browsingContextGlobal, "Check _browsingContextGlobal exists"); + ok(!LMP._browsingContextGlobal.get(99), "BrowsingContext 99 shouldn't exist yet"); + info("Stubbing BrowsingContext.get(99)"); + sinon.stub(LMP._browsingContextGlobal, "get").withArgs(99).callsFake(() => { + return { + currentWindowGlobal: { + documentPrincipal: Services.scriptSecurityManager.createCodebasePrincipalFromOrigin("https://www.example.com^userContextId=6"), + }, + }; + }); + ok(LMP._browsingContextGlobal.get(99), "Checking BrowsingContext.get(99) stub"); + + let password1 = LMP.getGeneratedPassword(99); + notEqual(password1, null, "Check password was returned"); + equal(password1.length, 15, "Check password length"); + equal(LMP._generatedPasswordsByPrincipalOrigin.size, 1, "1 added to cache"); + equal(LMP._generatedPasswordsByPrincipalOrigin.get("https://www.example.com^userContextId=6"), + password1, "Cache key and value"); + let password2 = LMP.getGeneratedPassword(99); + equal(password1, password2, "Same password should be returned for the same origin"); + + info("Changing the documentPrincipal to simulate a navigation in the frame"); + LMP._browsingContextGlobal.get.restore(); + sinon.stub(LMP._browsingContextGlobal, "get").withArgs(99).callsFake(() => { + return { + currentWindowGlobal: { + documentPrincipal: Services.scriptSecurityManager.createCodebasePrincipalFromOrigin("https://www.mozilla.org^userContextId=2"), + }, + }; + }); + let password3 = LMP.getGeneratedPassword(99); + notEqual(password2, password3, "Different password for a different origin for the same BC"); + equal(password3.length, 15, "Check password3 length"); + + info("Now checks cases where null should be returned"); + + Services.prefs.setBoolPref("signon.rememberSignons", false); + equal(LMP.getGeneratedPassword(99), null, "Prevented when pwmgr disabled"); + Services.prefs.setBoolPref("signon.rememberSignons", true); + + Services.prefs.setBoolPref("signon.generation.available", false); + equal(LMP.getGeneratedPassword(99), null, "Prevented when unavailable"); + Services.prefs.setBoolPref("signon.generation.available", true); + + Services.prefs.setBoolPref("signon.generation.enabled", false); + equal(LMP.getGeneratedPassword(99), null, "Prevented when disabled"); + Services.prefs.setBoolPref("signon.generation.enabled", true); + + equal(LMP.getGeneratedPassword(123), null, "Prevented when browsingContext is missing"); +}); diff --git a/toolkit/components/passwordmgr/test/unit/xpcshell.ini b/toolkit/components/passwordmgr/test/unit/xpcshell.ini index 7f459174197a..978962d3d029 100644 --- a/toolkit/components/passwordmgr/test/unit/xpcshell.ini +++ b/toolkit/components/passwordmgr/test/unit/xpcshell.ini @@ -27,6 +27,8 @@ run-if = buildapp == "browser" [test_isOriginMatching.js] [test_isUsernameFieldType.js] [test_legacy_empty_formSubmitURL.js] +[test_LoginManagerParent_doAutocompleteSearch.js] +[test_LoginManagerParent_getGeneratedPassword.js] [test_legacy_validation.js] [test_login_autocomplete_result.js] skip-if = os == "android"