summaryrefslogtreecommitdiffstats
path: root/services/sync/tests/unit/test_password_tracker.js
diff options
context:
space:
mode:
Diffstat (limited to 'services/sync/tests/unit/test_password_tracker.js')
-rw-r--r--services/sync/tests/unit/test_password_tracker.js248
1 files changed, 248 insertions, 0 deletions
diff --git a/services/sync/tests/unit/test_password_tracker.js b/services/sync/tests/unit/test_password_tracker.js
new file mode 100644
index 0000000000..77b46d1d2c
--- /dev/null
+++ b/services/sync/tests/unit/test_password_tracker.js
@@ -0,0 +1,248 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const { PasswordEngine, LoginRec } = ChromeUtils.importESModule(
+ "resource://services-sync/engines/passwords.sys.mjs"
+);
+const { Service } = ChromeUtils.importESModule(
+ "resource://services-sync/service.sys.mjs"
+);
+
+let engine;
+let store;
+let tracker;
+
+add_task(async function setup() {
+ await Service.engineManager.register(PasswordEngine);
+ engine = Service.engineManager.get("passwords");
+ store = engine._store;
+ tracker = engine._tracker;
+});
+
+add_task(async function test_tracking() {
+ let recordNum = 0;
+
+ _("Verify we've got an empty tracker to work with.");
+ let changes = await engine.getChangedIDs();
+ do_check_empty(changes);
+
+ let exceptionHappened = false;
+ try {
+ await tracker.getChangedIDs();
+ } catch (ex) {
+ exceptionHappened = true;
+ }
+ ok(exceptionHappened, "tracker does not keep track of changes");
+
+ async function createPassword() {
+ _("RECORD NUM: " + recordNum);
+ let record = new LoginRec("passwords", "GUID" + recordNum);
+ record.cleartext = {
+ id: "GUID" + recordNum,
+ hostname: "http://foo.bar.com",
+ formSubmitURL: "http://foo.bar.com",
+ username: "john" + recordNum,
+ password: "smith",
+ usernameField: "username",
+ passwordField: "password",
+ };
+ recordNum++;
+ let login = store._nsLoginInfoFromRecord(record);
+ await Services.logins.addLoginAsync(login);
+ await tracker.asyncObserver.promiseObserversComplete();
+ }
+
+ try {
+ tracker.start();
+ await createPassword();
+ changes = await engine.getChangedIDs();
+ do_check_attribute_count(changes, 1);
+ Assert.equal(tracker.score, SCORE_INCREMENT_XLARGE);
+ Assert.equal(changes.GUID0.counter, 1);
+ Assert.ok(typeof changes.GUID0.modified, "number");
+
+ _("Starting twice won't do any harm.");
+ tracker.start();
+ await createPassword();
+ changes = await engine.getChangedIDs();
+ do_check_attribute_count(changes, 2);
+ Assert.equal(tracker.score, SCORE_INCREMENT_XLARGE * 2);
+ Assert.equal(changes.GUID0.counter, 1);
+ Assert.equal(changes.GUID1.counter, 1);
+
+ // The tracker doesn't keep track of changes, so 3 changes
+ // should still be returned, but the score is not updated.
+ _("Let's stop tracking again.");
+ tracker.resetScore();
+ await tracker.stop();
+ await createPassword();
+ changes = await engine.getChangedIDs();
+ do_check_attribute_count(changes, 3);
+ Assert.equal(tracker.score, 0);
+ Assert.equal(changes.GUID0.counter, 1);
+ Assert.equal(changes.GUID1.counter, 1);
+ Assert.equal(changes.GUID2.counter, 1);
+
+ _("Stopping twice won't do any harm.");
+ await tracker.stop();
+ await createPassword();
+ changes = await engine.getChangedIDs();
+ do_check_attribute_count(changes, 4);
+ Assert.equal(tracker.score, 0);
+ } finally {
+ _("Clean up.");
+ await store.wipe();
+ tracker.resetScore();
+ await tracker.stop();
+ }
+});
+
+add_task(async function test_onWipe() {
+ _("Verify we've got an empty tracker to work with.");
+ const changes = await engine.getChangedIDs();
+ do_check_empty(changes);
+ Assert.equal(tracker.score, 0);
+
+ try {
+ _("A store wipe should increment the score");
+ tracker.start();
+ await store.wipe();
+ await tracker.asyncObserver.promiseObserversComplete();
+
+ Assert.equal(tracker.score, SCORE_INCREMENT_XLARGE);
+ } finally {
+ tracker.resetScore();
+ await tracker.stop();
+ }
+});
+
+add_task(async function test_removeAllLogins() {
+ let recordNum = 0;
+ _("Verify that all tracked logins are removed.");
+
+ // Perform this test twice, the first time where a sync is not performed
+ // between adding and removing items and the second time where a sync is
+ // performed. In the former case, the logins will just be deleted because
+ // they have never been synced, so they won't be detected as changes. In
+ // the latter case, the logins have been synced so they will be marked for
+ // deletion.
+ for (let syncBeforeRemove of [false, true]) {
+ async function createPassword() {
+ _("RECORD NUM: " + recordNum);
+ let record = new LoginRec("passwords", "GUID" + recordNum);
+ record.cleartext = {
+ id: "GUID" + recordNum,
+ hostname: "http://foo.bar.com",
+ formSubmitURL: "http://foo.bar.com",
+ username: "john" + recordNum,
+ password: "smith",
+ usernameField: "username",
+ passwordField: "password",
+ };
+ recordNum++;
+ let login = store._nsLoginInfoFromRecord(record);
+ await Services.logins.addLoginAsync(login);
+
+ await tracker.asyncObserver.promiseObserversComplete();
+ }
+ try {
+ _("Tell tracker to start tracking changes");
+ tracker.start();
+ await createPassword();
+ await createPassword();
+ let changes = await engine.getChangedIDs();
+ do_check_attribute_count(changes, 2);
+ Assert.equal(tracker.score, SCORE_INCREMENT_XLARGE * 2);
+
+ if (syncBeforeRemove) {
+ let logins = await Services.logins.getAllLogins();
+ for (let login of logins) {
+ engine.markSynced(login.guid);
+ }
+ }
+
+ _("Tell sync to remove all logins");
+ Services.logins.removeAllUserFacingLogins();
+ await tracker.asyncObserver.promiseObserversComplete();
+ changes = await engine.getChangedIDs();
+ do_check_attribute_count(changes, syncBeforeRemove ? 2 : 0);
+ Assert.equal(tracker.score, SCORE_INCREMENT_XLARGE * 5);
+
+ let deletedGuids = await engine._store.getAllIDs();
+ if (syncBeforeRemove) {
+ for (let guid in deletedGuids) {
+ let deletedLogin = await engine._store._getLoginFromGUID(guid);
+
+ Assert.equal(deletedLogin.hostname, null, "deleted login hostname");
+ Assert.equal(
+ deletedLogin.formActionOrigin,
+ null,
+ "deleted login formActionOrigin"
+ );
+ Assert.equal(
+ deletedLogin.formSubmitURL,
+ null,
+ "deleted login formSubmitURL"
+ );
+ Assert.equal(deletedLogin.httpRealm, null, "deleted login httpRealm");
+ Assert.equal(deletedLogin.username, null, "deleted login username");
+ Assert.equal(deletedLogin.password, null, "deleted login password");
+ Assert.equal(
+ deletedLogin.usernameField,
+ "",
+ "deleted login usernameField"
+ );
+ Assert.equal(
+ deletedLogin.passwordField,
+ "",
+ "deleted login passwordField"
+ );
+ Assert.equal(
+ deletedLogin.unknownFields,
+ null,
+ "deleted login unknownFields"
+ );
+ Assert.equal(
+ deletedLogin.timeCreated,
+ 0,
+ "deleted login timeCreated"
+ );
+ Assert.equal(
+ deletedLogin.timeLastUsed,
+ 0,
+ "deleted login timeLastUsed"
+ );
+ Assert.equal(deletedLogin.timesUsed, 0, "deleted login timesUsed");
+
+ // These fields are not reset when the login is removed.
+ Assert.ok(deletedLogin.guid.startsWith("GUID"), "deleted login guid");
+ Assert.equal(
+ deletedLogin.everSynced,
+ true,
+ "deleted login everSynced"
+ );
+ Assert.equal(
+ deletedLogin.syncCounter,
+ 2,
+ "deleted login syncCounter"
+ );
+ Assert.ok(
+ deletedLogin.timePasswordChanged > 0,
+ "deleted login timePasswordChanged"
+ );
+ }
+ } else {
+ Assert.equal(
+ Object.keys(deletedGuids).length,
+ 0,
+ "no logins remain after removeAllUserFacingLogins"
+ );
+ }
+ } finally {
+ _("Clean up.");
+ await store.wipe();
+ tracker.resetScore();
+ await tracker.stop();
+ }
+ }
+});