summaryrefslogtreecommitdiffstats
path: root/security/manager/ssl/tests/mochitest/browser/browser_exportP12_passwordUI.js
blob: fc7591ece625647fde37ad36eb2079f99bb400f7 (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
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
"use strict";

// Tests that the UI for setting the password on a to be exported PKCS #12 file:
//   1. Correctly requires the password to be typed in twice as confirmation.
//   2. Calculates and displays the strength of said password.

/**
 * @typedef {TestCase}
 * @type Object
 * @property {String} name
 *           The name of the test case for display purposes.
 * @property {String} password1
 *           The password to enter into the first password textbox.
 * @property {String} password2
 *           The password to enter into the second password textbox.
 * @property {String} strength
 *           The expected strength of the password in the range [0, 100].
 */

/**
 * A list of test cases representing various inputs to the password textboxes.
 * @type TestCase[]
 */
const TEST_CASES = [
  { name: "empty",
    password1: "",
    password2: "",
    strength: "0" },
  { name: "match-weak",
    password1: "foo",
    password2: "foo",
    strength: "10" },
  { name: "match-medium",
    password1: "foo123",
    password2: "foo123",
    strength: "60" },
  { name: "match-strong",
    password1: "fooBARBAZ 1234567890`~!@#$%^&*()-_=+{[}]|\\:;'\",<.>/?一二三",
    password2: "fooBARBAZ 1234567890`~!@#$%^&*()-_=+{[}]|\\:;'\",<.>/?一二三",
    strength: "100" },
  { name: "mismatch-weak",
    password1: "foo",
    password2: "bar",
    strength: "10" },
  { name: "mismatch-medium",
    password1: "foo123",
    password2: "bar",
    strength: "60" },
  { name: "mismatch-strong",
    password1: "fooBARBAZ 1234567890`~!@#$%^&*()-_=+{[}]|\\:;'\",<.>/?一二三",
    password2: "bar",
    strength: "100" },
];

/**
 * Opens the dialog shown to set the password on a PKCS #12 file being exported.
 *
 * @returns {Promise}
 *          A promise that resolves when the dialog has finished loading, with
 *          an array consisting of:
 *            1. The window of the opened dialog.
 *            2. The return value nsIWritablePropertyBag2 passed to the dialog.
 */
function openSetP12PasswordDialog() {
  let returnVals = Cc["@mozilla.org/hash-property-bag;1"]
                     .createInstance(Ci.nsIWritablePropertyBag2);
  let win = window.openDialog("chrome://pippki/content/setp12password.xul", "",
                              "", returnVals);
  return new Promise((resolve, reject) => {
    win.addEventListener("load", function onLoad() {
      win.removeEventListener("load", onLoad);
      resolve([win, returnVals]);
    });
  });
}

// Tests that the first password textbox is the element that is initially
// focused.
add_task(function* testFocus() {
  let [win, retVals] = yield openSetP12PasswordDialog();
  Assert.equal(win.document.activeElement,
               win.document.getElementById("pw1").inputField,
               "First password textbox should have focus");
  yield BrowserTestUtils.closeWindow(win);
});

// Tests that the password strength algorithm used is reasonable, and that the
// Accept button is only enabled if the two passwords match.
add_task(function* testPasswordStrengthAndEquality() {
  let [win, retVals] = yield openSetP12PasswordDialog();
  let password1Textbox = win.document.getElementById("pw1");
  let password2Textbox = win.document.getElementById("pw2");
  let strengthProgressBar = win.document.getElementById("pwmeter");

  for (let testCase of TEST_CASES) {
    password1Textbox.value = testCase.password1;
    password2Textbox.value = testCase.password2;
    // Setting the value of the password textboxes via |.value| apparently
    // doesn't cause the oninput handlers to be called, so we do it here.
    password1Textbox.oninput();
    password2Textbox.oninput();

    Assert.equal(win.document.documentElement.getButton("accept").disabled,
                 password1Textbox.value != password2Textbox.value,
                 "Actual and expected accept button disable state should " +
                 `match for ${testCase.name}`);
    Assert.equal(strengthProgressBar.value, testCase.strength,
                 "Actual and expected strength value should match for" +
                 `${testCase.name}`);
  }

  yield BrowserTestUtils.closeWindow(win);
});

// Test that the right values are returned when the dialog is accepted.
add_task(function* testAcceptDialogReturnValues() {
  let [win, retVals] = yield openSetP12PasswordDialog();
  const password = "fooBAR 1234567890`~!@#$%^&*()-_=+{[}]|\\:;'\",<.>/?一二三";
  win.document.getElementById("pw1").value = password;
  win.document.getElementById("pw2").value = password;
  info("Accepting dialog");
  win.document.getElementById("setp12password").acceptDialog();
  yield BrowserTestUtils.windowClosed(win);

  Assert.ok(retVals.get("confirmedPassword"),
            "Return value should signal user confirmed a password");
  Assert.equal(retVals.get("password"), password,
               "Actual and expected password should match");
});

// Test that the right values are returned when the dialog is canceled.
add_task(function* testCancelDialogReturnValues() {
  let [win, retVals] = yield openSetP12PasswordDialog();
  info("Canceling dialog");
  win.document.getElementById("setp12password").cancelDialog();
  yield BrowserTestUtils.windowClosed(win);

  Assert.ok(!retVals.get("confirmedPassword"),
            "Return value should signal user didn't confirm a password");
});