summaryrefslogtreecommitdiffstats
path: root/security/manager/ssl/tests/mochitest/browser/browser_deleteCert_ui.js
blob: b0ac8f95c153d8b7df1e929688fcd0da27ef31fc (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
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
"use strict";

// Tests various aspects of the cert delete confirmation dialog.
// Among other things, tests that for each type of cert that can be deleted:
// 1. The various lines of explanation text are correctly set.
// 2. The implementation correctly falls back through multiple cert attributes
//    to determine what to display to represent a cert.

/**
 * An array of tree items corresponding to TEST_CASES.
 * @type nsICertTreeItem[]
 */
var gCertArray = [];

const FAKE_HOST_PORT = "Fake host and port";

/**
 * @typedef {TestCase}
 * @type Object
 * @property {String} certFilename
 *           Filename of the cert, or null if we don't want to import a cert for
 *           this test case (i.e. we expect the hostPort attribute of
 *           nsICertTreeItem to be used).
 * @property {String} expectedDisplayString
 *           The string we expect the UI to display to represent the given cert.
 */

/**
 * A list of test cases representing certs that get "deleted".
 * @type TestCase[]
 */
const TEST_CASES = [
  { certFilename: null,
    expectedDisplayString: FAKE_HOST_PORT },
  { certFilename: "has-cn.pem",
    expectedDisplayString: "Foo" },
  { certFilename: "has-ou.pem",
    expectedDisplayString: "Bar" },
  { certFilename: "has-o.pem",
    expectedDisplayString: "Baz" },
  { certFilename: "has-non-empty-subject.pem",
    expectedDisplayString: "C=US" },
  { certFilename: "has-empty-subject.pem",
    expectedDisplayString: "Certificate with serial number: 0A" },
];

/**
 * Opens the cert delete confirmation dialog.
 *
 * @param {String} tabID
 *        The ID of the cert category tab the certs to delete belong to.
 * @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 object passed to the dialog.
 */
function openDeleteCertConfirmDialog(tabID) {
  let retVals = {
    deleteConfirmed: false,
  };
  let win = window.openDialog("chrome://pippki/content/deletecert.xul", "", "",
                              tabID, gCertArray, retVals);
  return new Promise((resolve, reject) => {
    win.addEventListener("load", function onLoad() {
      win.removeEventListener("load", onLoad);
      resolve([win, retVals]);
    });
  });
}

add_task(function* setup() {
  for (let testCase of TEST_CASES) {
    let cert = null;
    if (testCase.certFilename) {
      cert = yield readCertificate(testCase.certFilename, ",,");
    }
    let certTreeItem = {
      hostPort: FAKE_HOST_PORT,
      cert: cert,
      QueryInterface(iid) {
        if (iid.equals(Ci.nsICertTreeItem)) {
          return this;
        }

        throw new Error(Cr.NS_ERROR_NO_INTERFACE);
      }
    };
    gCertArray.push(certTreeItem);
  }
});

/**
 * Test helper for the below test cases.
 *
 * @param {String} tabID
 *        ID of the cert category tab the certs to delete belong to.
 * @param {String} expectedTitle
 *        Title the dialog is expected to have.
 * @param {String} expectedConfirmMsg
 *        Confirmation message the dialog is expected to show.
 * @param {String} expectedImpact
 *        Impact the dialog is expected to show.
 */
function* testHelper(tabID, expectedTitle, expectedConfirmMsg, expectedImpact) {
  let [win, retVals] = yield openDeleteCertConfirmDialog(tabID);
  let certList = win.document.getElementById("certlist");

  Assert.equal(win.document.title, expectedTitle,
               `Actual and expected titles should match for ${tabID}`);
  Assert.equal(win.document.getElementById("confirm").textContent,
               expectedConfirmMsg,
               `Actual and expected confirm message should match for ${tabID}`);
  Assert.equal(win.document.getElementById("impact").textContent,
               expectedImpact,
               `Actual and expected impact should match for ${tabID}`);

  Assert.equal(certList.itemCount, TEST_CASES.length,
               `No. of certs displayed should match for ${tabID}`);
  for (let i = 0; i < certList.itemCount; i++) {
    Assert.equal(certList.getItemAtIndex(i).label,
                 TEST_CASES[i].expectedDisplayString,
                 "Actual and expected display string should match for " +
                 `index ${i} for ${tabID}`);
  }

  yield BrowserTestUtils.closeWindow(win);
}

// Test deleting certs from the "Your Certificates" tab.
add_task(function* testDeletePersonalCerts() {
  const expectedTitle = "Delete your Certificates";
  const expectedConfirmMsg =
    "Are you sure you want to delete these certificates?";
  const expectedImpact =
    "If you delete one of your own certificates, you can no longer use it to " +
    "identify yourself.";
  yield* testHelper("mine_tab", expectedTitle, expectedConfirmMsg,
                    expectedImpact);
});

// Test deleting certs from the "People" tab.
add_task(function* testDeleteOtherPeopleCerts() {
  const expectedTitle = "Delete E-Mail Certificates";
  // ’ doesn't seem to work when embedded in the following literals, which is
  // why escape codes are used instead.
  const expectedConfirmMsg =
    "Are you sure you want to delete these people\u2019s e-mail certificates?";
  const expectedImpact =
    "If you delete a person\u2019s e-mail certificate, you will no longer be " +
    "able to send encrypted e-mail to that person.";
  yield* testHelper("others_tab", expectedTitle, expectedConfirmMsg,
                    expectedImpact);
});

// Test deleting certs from the "Servers" tab.
add_task(function* testDeleteServerCerts() {
  const expectedTitle = "Delete Server Certificate Exceptions";
  const expectedConfirmMsg =
    "Are you sure you want to delete these server exceptions?";
  const expectedImpact =
    "If you delete a server exception, you restore the usual security checks " +
    "for that server and require it uses a valid certificate.";
  yield* testHelper("websites_tab", expectedTitle, expectedConfirmMsg,
                    expectedImpact);
});

// Test deleting certs from the "Authorities" tab.
add_task(function* testDeleteCACerts() {
  const expectedTitle = "Delete or Distrust CA Certificates";
  const expectedConfirmMsg =
    "You have requested to delete these CA certificates. For built-in " +
    "certificates all trust will be removed, which has the same effect. Are " +
    "you sure you want to delete or distrust?";
  const expectedImpact =
    "If you delete or distrust a certificate authority (CA) certificate, " +
    "this application will no longer trust any certificates issued by that CA.";
  yield* testHelper("ca_tab", expectedTitle, expectedConfirmMsg,
                    expectedImpact);
});

// Test deleting certs from the "Other" tab.
add_task(function* testDeleteOtherCerts() {
  const expectedTitle = "Delete Certificates";
  const expectedConfirmMsg =
    "Are you sure you want to delete these certificates?";
  const expectedImpact = "";
  yield* testHelper("orphan_tab", expectedTitle, expectedConfirmMsg,
                    expectedImpact);
});

// Test that the right values are returned when the dialog is accepted.
add_task(function* testAcceptDialogReturnValues() {
  let [win, retVals] = yield openDeleteCertConfirmDialog("ca_tab" /*arbitrary*/);
  info("Accepting dialog");
  win.document.getElementById("deleteCertificate").acceptDialog();
  yield BrowserTestUtils.windowClosed(win);

  Assert.ok(retVals.deleteConfirmed,
            "Return value should signal user accepted");
});

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

  Assert.ok(!retVals.deleteConfirmed,
            "Return value should signal user did not accept");
});