summaryrefslogtreecommitdiffstats
path: root/browser/components/aboutlogins/tests/unit/test_getPotentialBreachesByLoginGUID.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/aboutlogins/tests/unit/test_getPotentialBreachesByLoginGUID.js')
-rw-r--r--browser/components/aboutlogins/tests/unit/test_getPotentialBreachesByLoginGUID.js327
1 files changed, 327 insertions, 0 deletions
diff --git a/browser/components/aboutlogins/tests/unit/test_getPotentialBreachesByLoginGUID.js b/browser/components/aboutlogins/tests/unit/test_getPotentialBreachesByLoginGUID.js
new file mode 100644
index 0000000000..a868572a6a
--- /dev/null
+++ b/browser/components/aboutlogins/tests/unit/test_getPotentialBreachesByLoginGUID.js
@@ -0,0 +1,327 @@
+/**
+ * Test LoginBreaches.getPotentialBreachesByLoginGUID
+ */
+
+"use strict";
+
+const { RemoteSettings } = ChromeUtils.importESModule(
+ "resource://services-settings/remote-settings.sys.mjs"
+);
+
+// Initializing BrowserGlue requires a profile on Windows.
+do_get_profile();
+
+const gBrowserGlue = Cc["@mozilla.org/browser/browserglue;1"].getService(
+ Ci.nsIObserver
+);
+
+ChromeUtils.defineESModuleGetters(this, {
+ LoginBreaches: "resource:///modules/LoginBreaches.sys.mjs",
+});
+
+const TEST_BREACHES = [
+ {
+ AddedDate: "2018-12-20T23:56:26Z",
+ BreachDate: "2018-12-16",
+ Domain: "breached.com",
+ Name: "Breached",
+ PwnCount: 1643100,
+ DataClasses: ["Email addresses", "Usernames", "Passwords", "IP addresses"],
+ _status: "synced",
+ id: "047940fe-d2fd-4314-b636-b4a952ee0043",
+ last_modified: "1541615610052",
+ schema: "1541615609018",
+ },
+ {
+ AddedDate: "2018-12-20T23:56:26Z",
+ BreachDate: "2018-12-16",
+ Domain: "breached-subdomain.host.com",
+ Name: "Only a Sub-Domain was Breached",
+ PwnCount: 2754200,
+ DataClasses: ["Email addresses", "Usernames", "Passwords", "IP addresses"],
+ _status: "synced",
+ id: "047940fe-d2fd-4314-b636-b4a952ee0044",
+ last_modified: "1541615610052",
+ schema: "1541615609018",
+ },
+ {
+ AddedDate: "2018-12-20T23:56:26Z",
+ BreachDate: "2018-12-16",
+ Domain: "breached-site-without-passwords.com",
+ Name: "Breached Site without passwords",
+ PwnCount: 987654,
+ DataClasses: ["Email addresses", "Usernames", "IP addresses"],
+ _status: "synced",
+ id: "047940fe-d2fd-4314-b636-b4a952ee0045",
+ last_modified: "1541615610052",
+ schema: "1541615609018",
+ },
+];
+
+const CRASHING_URI_LOGIN = LoginTestUtils.testData.formLogin({
+ origin: "chrome://grwatcher",
+ formActionOrigin: "https://www.example.com",
+ username: "username",
+ password: "password",
+ timePasswordChanged: new Date("2018-12-15").getTime(),
+});
+const NOT_BREACHED_LOGIN = LoginTestUtils.testData.formLogin({
+ origin: "https://www.example.com",
+ formActionOrigin: "https://www.example.com",
+ username: "username",
+ password: "password",
+ timePasswordChanged: new Date("2018-12-15").getTime(),
+});
+const BREACHED_LOGIN = LoginTestUtils.testData.formLogin({
+ origin: "https://www.breached.com",
+ formActionOrigin: "https://www.breached.com",
+ username: "username",
+ password: "password",
+ timePasswordChanged: new Date("2018-12-15").getTime(),
+});
+const NOT_BREACHED_SUBDOMAIN_LOGIN = LoginTestUtils.testData.formLogin({
+ origin: "https://not-breached-subdomain.host.com",
+ formActionOrigin: "https://not-breached-subdomain.host.com",
+ username: "username",
+ password: "password",
+});
+const BREACHED_SUBDOMAIN_LOGIN = LoginTestUtils.testData.formLogin({
+ origin: "https://breached-subdomain.host.com",
+ formActionOrigin: "https://breached-subdomain.host.com",
+ username: "username",
+ password: "password",
+ timePasswordChanged: new Date("2018-12-15").getTime(),
+});
+const LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS =
+ LoginTestUtils.testData.formLogin({
+ origin: "https://breached-site-without-passwords.com",
+ formActionOrigin: "https://breached-site-without-passwords.com",
+ username: "username",
+ password: "password",
+ timePasswordChanged: new Date("2018-12-15").getTime(),
+ });
+const LOGIN_WITH_NON_STANDARD_URI = LoginTestUtils.testData.formLogin({
+ origin: "someApp://random/path/to/login",
+ formActionOrigin: "someApp://random/path/to/login",
+ username: "username",
+ password: "password",
+ timePasswordChanged: new Date("2018-12-15").getTime(),
+});
+
+add_task(async function test_notBreachedLogin() {
+ await Services.logins.addLoginAsync(NOT_BREACHED_LOGIN);
+ const breachesByLoginGUID =
+ await LoginBreaches.getPotentialBreachesByLoginGUID(
+ [NOT_BREACHED_LOGIN],
+ TEST_BREACHES
+ );
+ Assert.strictEqual(
+ breachesByLoginGUID.size,
+ 0,
+ "Should be 0 breached logins."
+ );
+});
+
+add_task(async function test_breachedLogin() {
+ await Services.logins.addLoginAsync(BREACHED_LOGIN);
+ const breachesByLoginGUID =
+ await LoginBreaches.getPotentialBreachesByLoginGUID(
+ [NOT_BREACHED_LOGIN, BREACHED_LOGIN],
+ TEST_BREACHES
+ );
+ Assert.strictEqual(
+ breachesByLoginGUID.size,
+ 1,
+ "Should be 1 breached login: " + BREACHED_LOGIN.origin
+ );
+ Assert.strictEqual(
+ breachesByLoginGUID.get(BREACHED_LOGIN.guid).breachAlertURL,
+ "https://monitor.firefox.com/breach-details/Breached?utm_source=firefox-desktop&utm_medium=referral&utm_campaign=about-logins&utm_content=about-logins",
+ "Breach alert link should be equal to the breachAlertURL"
+ );
+});
+
+add_task(async function test_breachedLoginAfterCrashingUriLogin() {
+ await Services.logins.addLoginAsync(CRASHING_URI_LOGIN);
+
+ const breachesByLoginGUID =
+ await LoginBreaches.getPotentialBreachesByLoginGUID(
+ [CRASHING_URI_LOGIN, BREACHED_LOGIN],
+ TEST_BREACHES
+ );
+ Assert.strictEqual(
+ breachesByLoginGUID.size,
+ 1,
+ "Should be 1 breached login: " + BREACHED_LOGIN.origin
+ );
+ Assert.strictEqual(
+ breachesByLoginGUID.get(BREACHED_LOGIN.guid).breachAlertURL,
+ "https://monitor.firefox.com/breach-details/Breached?utm_source=firefox-desktop&utm_medium=referral&utm_campaign=about-logins&utm_content=about-logins",
+ "Breach alert link should be equal to the breachAlertURL"
+ );
+});
+
+add_task(async function test_notBreachedSubdomain() {
+ await Services.logins.addLoginAsync(NOT_BREACHED_SUBDOMAIN_LOGIN);
+
+ const breachesByLoginGUID =
+ await LoginBreaches.getPotentialBreachesByLoginGUID(
+ [NOT_BREACHED_LOGIN, NOT_BREACHED_SUBDOMAIN_LOGIN],
+ TEST_BREACHES
+ );
+ Assert.strictEqual(
+ breachesByLoginGUID.size,
+ 0,
+ "Should be 0 breached logins."
+ );
+});
+
+add_task(async function test_breachedSubdomain() {
+ await Services.logins.addLoginAsync(BREACHED_SUBDOMAIN_LOGIN);
+
+ const breachesByLoginGUID =
+ await LoginBreaches.getPotentialBreachesByLoginGUID(
+ [NOT_BREACHED_SUBDOMAIN_LOGIN, BREACHED_SUBDOMAIN_LOGIN],
+ TEST_BREACHES
+ );
+ Assert.strictEqual(
+ breachesByLoginGUID.size,
+ 1,
+ "Should be 1 breached login: " + BREACHED_SUBDOMAIN_LOGIN.origin
+ );
+});
+
+add_task(async function test_breachedSiteWithoutPasswords() {
+ await Services.logins.addLoginAsync(
+ LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS
+ );
+
+ const breachesByLoginGUID =
+ await LoginBreaches.getPotentialBreachesByLoginGUID(
+ [LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS],
+ TEST_BREACHES
+ );
+ Assert.strictEqual(
+ breachesByLoginGUID.size,
+ 0,
+ "Should be 0 breached login: " +
+ LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS.origin
+ );
+});
+
+add_task(async function test_breachAlertHiddenAfterDismissal() {
+ BREACHED_LOGIN.guid = "{d2de5ac1-4de6-e544-a7af-1f75abcba92b}";
+
+ await Services.logins.initializationPromise;
+ const storageJSON = Services.logins.wrappedJSObject._storage.wrappedJSObject;
+
+ storageJSON.recordBreachAlertDismissal(BREACHED_LOGIN.guid);
+
+ const breachesByLoginGUID =
+ await LoginBreaches.getPotentialBreachesByLoginGUID(
+ [BREACHED_LOGIN, NOT_BREACHED_LOGIN],
+ TEST_BREACHES
+ );
+ Assert.strictEqual(
+ breachesByLoginGUID.size,
+ 0,
+ "Should be 0 breached logins after dismissal: " + BREACHED_LOGIN.origin
+ );
+
+ info("Clear login storage");
+ Services.logins.removeAllUserFacingLogins();
+
+ const breachesByLoginGUID2 =
+ await LoginBreaches.getPotentialBreachesByLoginGUID(
+ [BREACHED_LOGIN, NOT_BREACHED_LOGIN],
+ TEST_BREACHES
+ );
+ Assert.strictEqual(
+ breachesByLoginGUID2.size,
+ 1,
+ "Breached login should re-appear after clearing storage: " +
+ BREACHED_LOGIN.origin
+ );
+});
+
+add_task(async function test_newBreachAfterDismissal() {
+ TEST_BREACHES[0].AddedDate = new Date().toISOString();
+
+ const breachesByLoginGUID =
+ await LoginBreaches.getPotentialBreachesByLoginGUID(
+ [BREACHED_LOGIN, NOT_BREACHED_LOGIN],
+ TEST_BREACHES
+ );
+
+ Assert.strictEqual(
+ breachesByLoginGUID.size,
+ 1,
+ "Should be 1 breached login after new breach following the dismissal of a previous breach: " +
+ BREACHED_LOGIN.origin
+ );
+});
+
+add_task(async function test_ExceptionsThrownByNonStandardURIsAreCaught() {
+ await Services.logins.addLoginAsync(LOGIN_WITH_NON_STANDARD_URI);
+
+ const breachesByLoginGUID =
+ await LoginBreaches.getPotentialBreachesByLoginGUID(
+ [LOGIN_WITH_NON_STANDARD_URI, BREACHED_LOGIN],
+ TEST_BREACHES
+ );
+
+ Assert.strictEqual(
+ breachesByLoginGUID.size,
+ 1,
+ "Exceptions thrown by logins with non-standard URIs should be caught."
+ );
+});
+
+add_task(async function test_setBreachesFromRemoteSettingsSync() {
+ const login = NOT_BREACHED_SUBDOMAIN_LOGIN;
+ const nowExampleIsInBreachedRecords = [
+ {
+ AddedDate: "2018-12-20T23:56:26Z",
+ BreachDate: "2018-12-16",
+ Domain: "not-breached-subdomain.host.com",
+ Name: "not-breached-subdomain.host.com is now breached!",
+ PwnCount: 1643100,
+ DataClasses: [
+ "Email addresses",
+ "Usernames",
+ "Passwords",
+ "IP addresses",
+ ],
+ _status: "synced",
+ id: "047940fe-d2fd-4314-b636-b4a952ee0044",
+ last_modified: "1541615610052",
+ schema: "1541615609018",
+ },
+ ];
+ async function emitSync() {
+ await RemoteSettings(LoginBreaches.REMOTE_SETTINGS_COLLECTION).emit(
+ "sync",
+ { data: { current: nowExampleIsInBreachedRecords } }
+ );
+ }
+
+ const beforeSyncBreachesByLoginGUID =
+ await LoginBreaches.getPotentialBreachesByLoginGUID([login]);
+ Assert.strictEqual(
+ beforeSyncBreachesByLoginGUID.size,
+ 0,
+ "Should be 0 breached login before not-breached-subdomain.host.com is added to fxmonitor-breaches collection and synced: "
+ );
+ gBrowserGlue.observe(null, "browser-glue-test", "add-breaches-sync-handler");
+ const db = RemoteSettings(LoginBreaches.REMOTE_SETTINGS_COLLECTION).db;
+ await db.importChanges({}, Date.now(), [nowExampleIsInBreachedRecords[0]]);
+ await emitSync();
+
+ const breachesByLoginGUID =
+ await LoginBreaches.getPotentialBreachesByLoginGUID([login]);
+ Assert.strictEqual(
+ breachesByLoginGUID.size,
+ 1,
+ "Should be 1 breached login after not-breached-subdomain.host.com is added to fxmonitor-breaches collection and synced: "
+ );
+});