summaryrefslogtreecommitdiffstats
path: root/browser/components/aboutlogins/tests/browser/browser_alertDismissedAfterChangingPassword.js
blob: 623df38fcb15a478596b81622db2db018bcaf6c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

EXPECTED_BREACH = {
  AddedDate: "2018-12-20T23:56:26Z",
  BreachDate: "2018-12-16",
  Domain: "breached.example.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",
};

let VULNERABLE_TEST_LOGIN2 = new nsLoginInfo(
  "https://2.example.com",
  "https://2.example.com",
  null,
  "user2",
  "pass3",
  "username",
  "password"
);

add_setup(async function () {
  TEST_LOGIN1 = await addLogin(TEST_LOGIN1);
  VULNERABLE_TEST_LOGIN2 = await addLogin(VULNERABLE_TEST_LOGIN2);
  TEST_LOGIN3 = await addLogin(TEST_LOGIN3);
  await BrowserTestUtils.openNewForegroundTab({
    gBrowser,
    url: "about:logins",
  });
  registerCleanupFunction(() => {
    BrowserTestUtils.removeTab(gBrowser.selectedTab);
    Services.logins.removeAllUserFacingLogins();
  });
});

add_task(async function test_added_login_shows_breach_warning() {
  let browser = gBrowser.selectedBrowser;
  await SpecialPowers.spawn(
    browser,
    [[TEST_LOGIN1.guid, VULNERABLE_TEST_LOGIN2.guid, TEST_LOGIN3.guid]],
    async ([regularLoginGuid, vulnerableLoginGuid, breachedLoginGuid]) => {
      let loginList = Cu.waiveXrays(
        content.document.querySelector("login-list")
      );
      await ContentTaskUtils.waitForCondition(
        () => loginList.shadowRoot.querySelectorAll(".login-list-item").length,
        "Waiting for login-list to get populated"
      );
      let { listItem: regularListItem } = loginList._logins[regularLoginGuid];
      let { listItem: vulnerableListItem } =
        loginList._logins[vulnerableLoginGuid];
      let { listItem: breachedListItem } = loginList._logins[breachedLoginGuid];
      await ContentTaskUtils.waitForCondition(() => {
        return (
          !regularListItem.matches(".breached.vulnerable") &&
          vulnerableListItem.matches(".vulnerable") &&
          breachedListItem.matches(".breached")
        );
      }, `waiting for the list items to get their classes updated: ${regularListItem.className} / ${vulnerableListItem.className} / ${breachedListItem.className}`);
      Assert.ok(
        !regularListItem.classList.contains("breached") &&
          !regularListItem.classList.contains("vulnerable"),
        "regular login should not be marked breached or vulnerable: " +
          regularLoginGuid.className
      );
      Assert.ok(
        !vulnerableListItem.classList.contains("breached") &&
          vulnerableListItem.classList.contains("vulnerable"),
        "vulnerable login should be marked vulnerable: " +
          vulnerableListItem.className
      );
      Assert.ok(
        breachedListItem.classList.contains("breached") &&
          !breachedListItem.classList.contains("vulnerable"),
        "breached login should be marked breached: " +
          breachedListItem.className
      );

      breachedListItem.click();
      let loginItem = Cu.waiveXrays(
        content.document.querySelector("login-item")
      );
      await ContentTaskUtils.waitForCondition(() => {
        return loginItem._login && loginItem._login.guid == breachedLoginGuid;
      }, "waiting for breached login to get selected");
      Assert.ok(
        !ContentTaskUtils.is_hidden(
          loginItem.shadowRoot.querySelector(".breach-alert")
        ),
        "the breach alert should be visible"
      );
    }
  );

  if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
    info(
      "leaving test early since the remaining part of the test requires 'edit' mode which requires 'oskeystore' login"
    );
    return;
  }

  let reauthObserved = forceAuthTimeoutAndWaitForOSKeyStoreLogin({
    loginResult: true,
  });
  // Change the password on the breached login and check that the
  // login is no longer marked as breached. The vulnerable login
  // should still be marked as vulnerable afterwards.
  await SpecialPowers.spawn(browser, [], () => {
    let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
    loginItem.shadowRoot.querySelector(".edit-button").click();
  });
  await reauthObserved;
  await SpecialPowers.spawn(
    browser,
    [[TEST_LOGIN1.guid, VULNERABLE_TEST_LOGIN2.guid, TEST_LOGIN3.guid]],
    async ([regularLoginGuid, vulnerableLoginGuid, breachedLoginGuid]) => {
      let loginList = Cu.waiveXrays(
        content.document.querySelector("login-list")
      );
      let loginItem = Cu.waiveXrays(
        content.document.querySelector("login-item")
      );
      await ContentTaskUtils.waitForCondition(
        () => loginItem.dataset.editing == "true",
        "waiting for login-item to enter edit mode"
      );

      // The password display field is in the DOM when password input is unfocused.
      // To get the password input field, ensure it receives focus.
      let passwordInput = loginItem.shadowRoot.querySelector(
        "input[type='password']"
      );
      passwordInput.focus();
      passwordInput = loginItem.shadowRoot.querySelector(
        "input[name='password']"
      );

      const CHANGED_PASSWORD_VALUE = "changedPassword";
      passwordInput.value = CHANGED_PASSWORD_VALUE;
      let saveChangesButton = loginItem.shadowRoot.querySelector(
        ".save-changes-button"
      );
      saveChangesButton.click();

      await ContentTaskUtils.waitForCondition(() => {
        return (
          loginList._logins[breachedLoginGuid].login.password ==
          CHANGED_PASSWORD_VALUE
        );
      }, "waiting for stored login to get updated");

      Assert.ok(
        ContentTaskUtils.is_hidden(
          loginItem.shadowRoot.querySelector(".breach-alert")
        ),
        "the breach alert should be hidden now"
      );

      let { listItem: breachedListItem } = loginList._logins[breachedLoginGuid];
      let { listItem: vulnerableListItem } =
        loginList._logins[vulnerableLoginGuid];
      Assert.ok(
        !breachedListItem.classList.contains("breached") &&
          !breachedListItem.classList.contains("vulnerable"),
        "the originally breached login should no longer be marked as breached"
      );
      Assert.ok(
        !vulnerableListItem.classList.contains("breached") &&
          vulnerableListItem.classList.contains("vulnerable"),
        "vulnerable login should still be marked vulnerable: " +
          vulnerableListItem.className
      );

      // Change the password on the vulnerable login and check that the
      // login is no longer marked as vulnerable.
      vulnerableListItem.click();
      await ContentTaskUtils.waitForCondition(() => {
        return loginItem._login && loginItem._login.guid == vulnerableLoginGuid;
      }, "waiting for vulnerable login to get selected");
      Assert.ok(
        !ContentTaskUtils.is_hidden(
          loginItem.shadowRoot.querySelector(".vulnerable-alert")
        ),
        "the vulnerable alert should be visible"
      );
      loginItem.shadowRoot.querySelector(".edit-button").click();
      await ContentTaskUtils.waitForCondition(
        () => loginItem.dataset.editing == "true",
        "waiting for login-item to enter edit mode"
      );

      passwordInput.value = CHANGED_PASSWORD_VALUE;
      saveChangesButton.click();

      await ContentTaskUtils.waitForCondition(() => {
        return (
          loginList._logins[vulnerableLoginGuid].login.password ==
          CHANGED_PASSWORD_VALUE
        );
      }, "waiting for stored login to get updated");

      Assert.ok(
        ContentTaskUtils.is_hidden(
          loginItem.shadowRoot.querySelector(".vulnerable-alert")
        ),
        "the vulnerable alert should be hidden now"
      );
      Assert.equal(
        vulnerableListItem.querySelector(".alert-icon").src,
        "",
        ".alert-icon for the vulnerable list item should have its source removed"
      );
      vulnerableListItem = loginList._logins[vulnerableLoginGuid].listItem;
      Assert.ok(
        !vulnerableListItem.classList.contains("breached") &&
          !vulnerableListItem.classList.contains("vulnerable"),
        "vulnerable login should no longer be marked vulnerable: " +
          vulnerableListItem.className
      );
    }
  );
});