1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 /* import-globals-from pippki.js */
14 const { PrivateBrowsingUtils } = ChromeUtils.importESModule(
15 "resource://gre/modules/PrivateBrowsingUtils.sys.mjs"
18 function initExceptionDialog() {
20 gDialog = document.getElementById("exceptiondialog");
21 let warningText = document.getElementById("warningText");
22 document.l10n.setAttributes(warningText, "add-exception-branded-warning");
23 let confirmButton = gDialog.getButton("extra1");
24 let l10nUpdatedElements = [confirmButton, warningText];
25 confirmButton.disabled = true;
27 var args = window.arguments;
28 if (args && args[0]) {
29 if (args[0].location) {
30 // We were pre-seeded with a location.
31 document.getElementById("locationTextBox").value = args[0].location;
32 document.getElementById("checkCertButton").disabled = false;
34 if (args[0].securityInfo) {
35 gSecInfo = args[0].securityInfo;
36 gCert = gSecInfo.serverCert;
38 l10nUpdatedElements = l10nUpdatedElements.concat(updateCertStatus());
39 } else if (args[0].prefetchCert) {
40 // We can optionally pre-fetch the certificate too. Don't do this
41 // synchronously, since it would prevent the window from appearing
42 // until the fetch is completed, which could be multiple seconds.
43 // Instead, let's use a timer to spawn the actual fetch, but update
44 // the dialog to "checking..." state right away, so that the UI
45 // is appropriately responsive. Bug 453855
46 document.getElementById("checkCertButton").disabled = true;
48 l10nUpdatedElements = l10nUpdatedElements.concat(updateCertStatus());
50 window.setTimeout(checkCert, 0);
54 // Set out parameter to false by default
55 args[0].exceptionAdded = false;
59 "warningSupplemental",
63 "statusLongDescription",
67 let element = document.getElementById(id);
68 l10nUpdatedElements.push(element);
72 .translateElements(l10nUpdatedElements)
73 .then(() => window.sizeToContent());
75 document.addEventListener("dialogextra1", addException);
76 document.addEventListener("dialogextra2", checkCert);
80 * Helper function for checkCert. Set as the onerror/onload callbacks for an
81 * XMLHttpRequest. Sets gSecInfo, gCert, gBroken, and gChecking according to
82 * the load information from the request. Probably should not be used directly.
84 * @param {XMLHttpRequest} req
85 * The XMLHttpRequest created and sent by checkCert.
87 * The load or error event.
89 function grabCert(req, evt) {
90 if (req.channel && req.channel.securityInfo) {
91 gSecInfo = req.channel.securityInfo;
92 gCert = gSecInfo ? gSecInfo.serverCert : null;
94 gBroken = evt.type == "error";
97 .translateElements(updateCertStatus())
98 .then(() => window.sizeToContent());
102 * Attempt to download the certificate for the location specified, and populate
103 * the Certificate Status section with the result.
105 async function checkCert() {
110 await document.l10n.translateElements(updateCertStatus());
111 window.sizeToContent();
116 let req = new XMLHttpRequest();
117 req.open("GET", uri.prePath);
118 req.onerror = grabCert.bind(this, req);
119 req.onload = grabCert.bind(this, req);
123 await document.l10n.translateElements(updateCertStatus());
124 window.sizeToContent();
129 * Build and return a URI, based on the information supplied in the
130 * Certificate Location fields
133 * URI constructed from the information supplied on success, null
137 // Use fixup service instead of just ioservice's newURI since it's quite
138 // likely that the host will be supplied without a protocol prefix, resulting
139 // in malformed uri exceptions being thrown.
140 let locationTextBox = document.getElementById("locationTextBox");
141 let { preferredURI: uri } = Services.uriFixup.getFixupURIInfo(
142 locationTextBox.value
149 let mutator = uri.mutate();
150 if (uri.scheme == "http") {
151 mutator.setScheme("https");
154 if (uri.port == -1) {
155 mutator.setPort(443);
158 return mutator.finalize();
161 function resetDialog() {
162 document.getElementById("viewCertButton").disabled = true;
163 document.getElementById("permanent").disabled = true;
164 gDialog.getButton("extra1").disabled = true;
165 setText("headerDescription", "");
166 setText("statusDescription", "");
167 setText("statusLongDescription", "");
168 setText("status2Description", "");
169 setText("status2LongDescription", "");
170 setText("status3Description", "");
171 setText("status3LongDescription", "");
172 window.sizeToContent();
176 * Called by input textboxes to manage UI state
178 function handleTextChange() {
179 var checkCertButton = document.getElementById("checkCertButton");
180 checkCertButton.disabled = !document.getElementById("locationTextBox").value;
187 function updateCertStatus() {
188 var shortDesc, longDesc;
189 let l10nUpdatedElements = [];
192 var mms = "add-exception-domain-mismatch-short";
193 var mml = "add-exception-domain-mismatch-long";
194 var exs = "add-exception-expired-short";
195 var exl = "add-exception-expired-long";
196 var uts = "add-exception-unverified-or-bad-signature-short";
197 var utl = "add-exception-unverified-or-bad-signature-long";
199 gSecInfo.overridableErrorCategory ==
200 Ci.nsITransportSecurityInfo.ERROR_TRUST
205 gSecInfo.overridableErrorCategory ==
206 Ci.nsITransportSecurityInfo.ERROR_DOMAIN
211 gSecInfo.overridableErrorCategory ==
212 Ci.nsITransportSecurityInfo.ERROR_TIME
217 // In these cases, we do want to enable the "Add Exception" button
218 gDialog.getButton("extra1").disabled = false;
220 // If the Private Browsing service is available and the mode is active,
221 // don't store permanent exceptions, since they would persist after
222 // private browsing mode was disabled.
223 var inPrivateBrowsing = inPrivateBrowsingMode();
224 var pe = document.getElementById("permanent");
225 pe.disabled = inPrivateBrowsing;
226 pe.checked = !inPrivateBrowsing;
228 let headerDescription = document.getElementById("headerDescription");
229 document.l10n.setAttributes(
231 "add-exception-invalid-header"
233 l10nUpdatedElements.push(headerDescription);
235 shortDesc = "add-exception-valid-short";
236 longDesc = "add-exception-valid-long";
237 gDialog.getButton("extra1").disabled = true;
238 document.getElementById("permanent").disabled = true;
241 // We're done checking the certificate, so allow the user to check it again.
242 document.getElementById("checkCertButton").disabled = false;
243 document.getElementById("viewCertButton").disabled = false;
245 // Notify observers about the availability of the certificate
246 Services.obs.notifyObservers(null, "cert-exception-ui-ready");
247 } else if (gChecking) {
248 shortDesc = "add-exception-checking-short";
249 longDesc = "add-exception-checking-long";
250 // We're checking the certificate, so we disable the Get Certificate
251 // button to make sure that the user can't interrupt the process and
252 // trigger another certificate fetch.
253 document.getElementById("checkCertButton").disabled = true;
254 document.getElementById("viewCertButton").disabled = true;
255 gDialog.getButton("extra1").disabled = true;
256 document.getElementById("permanent").disabled = true;
258 shortDesc = "add-exception-no-cert-short";
259 longDesc = "add-exception-no-cert-long";
260 // We're done checking the certificate, so allow the user to check it again.
261 document.getElementById("checkCertButton").disabled = false;
262 document.getElementById("viewCertButton").disabled = true;
263 gDialog.getButton("extra1").disabled = true;
264 document.getElementById("permanent").disabled = true;
266 let statusDescription = document.getElementById("statusDescription");
267 let statusLongDescription = document.getElementById("statusLongDescription");
268 document.l10n.setAttributes(statusDescription, shortDesc);
269 document.l10n.setAttributes(statusLongDescription, longDesc);
270 l10nUpdatedElements.push(statusDescription);
271 l10nUpdatedElements.push(statusLongDescription);
274 return l10nUpdatedElements;
278 * Handle user request to display certificate details
280 function viewCertButtonClick() {
282 viewCertHelper(this, gCert);
287 * Handle user request to add an exception for the specified cert
289 function addException() {
290 if (!gCert || !gSecInfo) {
294 var overrideService = Cc["@mozilla.org/security/certoverride;1"].getService(
295 Ci.nsICertOverrideService
297 var permanentCheckbox = document.getElementById("permanent");
298 var shouldStorePermanently =
299 permanentCheckbox.checked && !inPrivateBrowsingMode();
301 overrideService.rememberValidityOverride(
306 !shouldStorePermanently
309 let args = window.arguments;
310 if (args && args[0]) {
311 args[0].exceptionAdded = true;
314 gDialog.acceptDialog();
318 * @returns {boolean} Whether this dialog is in private browsing mode.
320 function inPrivateBrowsingMode() {
321 return PrivateBrowsingUtils.isWindowPrivate(window);