summaryrefslogtreecommitdiffstats
path: root/toolkit/components/passwordmgr/test/unit/test_context_menu.js
blob: 722c13e155ed47ee53b3d4c7ce9114a46283d89d (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
/*
 * Test the password manager context menu.
 */

"use strict";

Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/LoginManagerContextMenu.jsm");

XPCOMUtils.defineLazyGetter(this, "_stringBundle", function() {
  return Services.strings.
         createBundle("chrome://passwordmgr/locale/passwordmgr.properties");
});

/**
 * Prepare data for the following tests.
 */
add_task(function* test_initialize() {
  for (let login of loginList()) {
    Services.logins.addLogin(login);
  }
});

/**
 * Tests if the LoginManagerContextMenu returns the correct login items.
 */
add_task(function* test_contextMenuAddAndRemoveLogins() {
  const DOCUMENT_CONTENT = "<form><input id='pw' type=password></form>";
  const INPUT_QUERY = "input[type='password']";

  let testHostnames = [
    "http://www.example.com",
    "http://www2.example.com",
    "http://www3.example.com",
    "http://empty.example.com",
  ];

  for (let hostname of testHostnames) {
    do_print("test for hostname: " + hostname);
    // Get expected logins for this test.
    let logins = getExpectedLogins(hostname);

    // Create the logins menuitems fragment.
    let {fragment, document} = createLoginsFragment(hostname, DOCUMENT_CONTENT, INPUT_QUERY);

    if (!logins.length) {
      Assert.ok(fragment === null, "Null returned. No logins where found.");
      continue;
    }
    let items = [...fragment.querySelectorAll("menuitem")];

    // Check if the items are those expected to be listed.
    Assert.ok(checkLoginItems(logins, items), "All expected logins found.");
    document.body.appendChild(fragment);

    // Try to clear the fragment.
    LoginManagerContextMenu.clearLoginsFromMenu(document);
    Assert.equal(fragment.querySelectorAll("menuitem").length, 0, "All items correctly cleared.");
  }

  Services.logins.removeAllLogins();
});

/**
 * Create a fragment with a menuitem for each login.
 */
function createLoginsFragment(url, content, elementQuery) {
  const CHROME_URL = "chrome://mock-chrome";

  // Create a mock document.
  let document = MockDocument.createTestDocument(CHROME_URL, content);
  let inputElement = document.querySelector(elementQuery);
  MockDocument.mockOwnerDocumentProperty(inputElement, document, url);

  // We also need a simple mock Browser object for this test.
  let browser = {
    ownerDocument: document
  };

  let URI = Services.io.newURI(url, null, null);
  return {
    document,
    fragment: LoginManagerContextMenu.addLoginsToMenu(inputElement, browser, URI),
  };
}

/**
 * Check if every login have it's corresponding menuitem.
 * Duplicates and empty usernames have a date appended.
 */
function checkLoginItems(logins, items) {
  function findDuplicates(unfilteredLoginList) {
    var seen = new Set();
    var duplicates = new Set();
    for (let login of unfilteredLoginList) {
      if (seen.has(login.username)) {
        duplicates.add(login.username);
      }
      seen.add(login.username);
    }
    return duplicates;
  }
  let duplicates = findDuplicates(logins);

  let dateAndTimeFormatter = new Intl.DateTimeFormat(undefined,
                             { day: "numeric", month: "short", year: "numeric" });
  for (let login of logins) {
    if (login.username && !duplicates.has(login.username)) {
      // If login is not duplicate and we can't find an item for it, fail.
      if (!items.find(item => item.label == login.username)) {
        return false;
      }
      continue;
    }

    let meta = login.QueryInterface(Ci.nsILoginMetaInfo);
    let time = dateAndTimeFormatter.format(new Date(meta.timePasswordChanged));
    // If login is duplicate, check if we have a login item with appended date.
    if (login.username && !items.find(item => item.label == login.username + " (" + time + ")")) {
      return false;
    }
    // If login is empty, check if we have a login item with appended date.
    if (!login.username &&
        !items.find(item => item.label == _stringBundle.GetStringFromName("noUsername") + " (" + time + ")")) {
      return false;
    }
  }
  return true;
}

/**
 * Gets the list of expected logins for a hostname.
 */
function getExpectedLogins(hostname) {
  return Services.logins.getAllLogins().filter(entry => entry["hostname"] === hostname);
}

function loginList() {
  return [
      new LoginInfo("http://www.example.com", "http://www.example.com", null,
                    "username1", "password",
                    "form_field_username", "form_field_password"),

      new LoginInfo("http://www.example.com", "http://www.example.com", null,
                    "username2", "password",
                    "form_field_username", "form_field_password"),

      new LoginInfo("http://www2.example.com", "http://www.example.com", null,
                    "username", "password",
                    "form_field_username", "form_field_password"),
      new LoginInfo("http://www2.example.com", "http://www2.example.com", null,
                    "username", "password2",
                    "form_field_username", "form_field_password"),
      new LoginInfo("http://www2.example.com", "http://www2.example.com", null,
                    "username2", "password2",
                    "form_field_username", "form_field_password"),

      new LoginInfo("http://www3.example.com", "http://www.example.com", null,
                    "", "password",
                    "form_field_username", "form_field_password"),
      new LoginInfo("http://www3.example.com", "http://www3.example.com", null,
                    "", "password2",
                    "form_field_username", "form_field_password"),
  ];
}