no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / security / manager / pki / resources / content / exceptionDialog.js
blob02fed06a385172dbaa9e1649f1f703c8f643a2d0
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 */
5 "use strict";
7 var gDialog;
8 var gSecInfo;
9 var gCert;
10 var gChecking;
11 var gBroken;
12 var gNeedReset;
14 const { PrivateBrowsingUtils } = ChromeUtils.importESModule(
15   "resource://gre/modules/PrivateBrowsingUtils.sys.mjs"
18 function initExceptionDialog() {
19   gNeedReset = false;
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;
37         gBroken = true;
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;
47         gChecking = true;
48         l10nUpdatedElements = l10nUpdatedElements.concat(updateCertStatus());
50         window.setTimeout(checkCert, 0);
51       }
52     }
54     // Set out parameter to false by default
55     args[0].exceptionAdded = false;
56   }
58   for (let id of [
59     "warningSupplemental",
60     "certLocationLabel",
61     "checkCertButton",
62     "statusDescription",
63     "statusLongDescription",
64     "viewCertButton",
65     "permanent",
66   ]) {
67     let element = document.getElementById(id);
68     l10nUpdatedElements.push(element);
69   }
71   document.l10n
72     .translateElements(l10nUpdatedElements)
73     .then(() => window.sizeToContent());
75   document.addEventListener("dialogextra1", addException);
76   document.addEventListener("dialogextra2", checkCert);
79 /**
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.
83  *
84  * @param {XMLHttpRequest} req
85  *        The XMLHttpRequest created and sent by checkCert.
86  * @param {Event} evt
87  *        The load or error event.
88  */
89 function grabCert(req, evt) {
90   if (req.channel && req.channel.securityInfo) {
91     gSecInfo = req.channel.securityInfo;
92     gCert = gSecInfo ? gSecInfo.serverCert : null;
93   }
94   gBroken = evt.type == "error";
95   gChecking = false;
96   document.l10n
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.
104  */
105 async function checkCert() {
106   gCert = null;
107   gSecInfo = null;
108   gChecking = true;
109   gBroken = false;
110   await document.l10n.translateElements(updateCertStatus());
111   window.sizeToContent();
113   let uri = getURI();
115   if (uri) {
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);
120     req.send(null);
121   } else {
122     gChecking = false;
123     await document.l10n.translateElements(updateCertStatus());
124     window.sizeToContent();
125   }
129  * Build and return a URI, based on the information supplied in the
130  * Certificate Location fields
132  * @returns {nsIURI}
133  *          URI constructed from the information supplied on success, null
134  *          otherwise.
135  */
136 function getURI() {
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
143   );
145   if (!uri) {
146     return null;
147   }
149   let mutator = uri.mutate();
150   if (uri.scheme == "http") {
151     mutator.setScheme("https");
152   }
154   if (uri.port == -1) {
155     mutator.setPort(443);
156   }
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
177  */
178 function handleTextChange() {
179   var checkCertButton = document.getElementById("checkCertButton");
180   checkCertButton.disabled = !document.getElementById("locationTextBox").value;
181   if (gNeedReset) {
182     gNeedReset = false;
183     resetDialog();
184   }
187 function updateCertStatus() {
188   var shortDesc, longDesc;
189   let l10nUpdatedElements = [];
190   if (gCert) {
191     if (gBroken) {
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";
198       if (
199         gSecInfo.overridableErrorCategory ==
200         Ci.nsITransportSecurityInfo.ERROR_TRUST
201       ) {
202         shortDesc = uts;
203         longDesc = utl;
204       } else if (
205         gSecInfo.overridableErrorCategory ==
206         Ci.nsITransportSecurityInfo.ERROR_DOMAIN
207       ) {
208         shortDesc = mms;
209         longDesc = mml;
210       } else if (
211         gSecInfo.overridableErrorCategory ==
212         Ci.nsITransportSecurityInfo.ERROR_TIME
213       ) {
214         shortDesc = exs;
215         longDesc = exl;
216       }
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(
230         headerDescription,
231         "add-exception-invalid-header"
232       );
233       l10nUpdatedElements.push(headerDescription);
234     } else {
235       shortDesc = "add-exception-valid-short";
236       longDesc = "add-exception-valid-long";
237       gDialog.getButton("extra1").disabled = true;
238       document.getElementById("permanent").disabled = true;
239     }
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;
257   } else {
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;
265   }
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);
273   gNeedReset = true;
274   return l10nUpdatedElements;
278  * Handle user request to display certificate details
279  */
280 function viewCertButtonClick() {
281   if (gCert) {
282     viewCertHelper(this, gCert);
283   }
287  * Handle user request to add an exception for the specified cert
288  */
289 function addException() {
290   if (!gCert || !gSecInfo) {
291     return;
292   }
294   var overrideService = Cc["@mozilla.org/security/certoverride;1"].getService(
295     Ci.nsICertOverrideService
296   );
297   var permanentCheckbox = document.getElementById("permanent");
298   var shouldStorePermanently =
299     permanentCheckbox.checked && !inPrivateBrowsingMode();
300   var uri = getURI();
301   overrideService.rememberValidityOverride(
302     uri.asciiHost,
303     uri.port,
304     {},
305     gCert,
306     !shouldStorePermanently
307   );
309   let args = window.arguments;
310   if (args && args[0]) {
311     args[0].exceptionAdded = true;
312   }
314   gDialog.acceptDialog();
318  * @returns {boolean} Whether this dialog is in private browsing mode.
319  */
320 function inPrivateBrowsingMode() {
321   return PrivateBrowsingUtils.isWindowPrivate(window);