Bug 1591749 - Enhance SeaMonkey's certificate / net error code r=frg a=frg CLOSED TREE
authorIan Neal <iann_cvs@blueyonder.co.uk>
Tue, 19 Nov 2019 17:50:29 +0100
changeset 32375 6eb03b94327b2bbc1fc131ed7721d6b6d3d2d8a2
parent 32374 0ad38cff04c455af45516175abb4f45c40e0de39
child 32376 9c0bd42275f46ca508ef3a3f43869e3e0b0c432e
push id230
push userfrgrahl@gmx.net
push dateTue, 19 Nov 2019 16:51:10 +0000
treeherdercomm-esr60@232db96d678a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfrg, frg
bugs1591749
Bug 1591749 - Enhance SeaMonkey's certificate / net error code r=frg a=frg CLOSED TREE
suite/base/content/certError.js
suite/base/content/certError.xhtml
suite/base/jar.mn
suite/locales/en-US/chrome/common/certError.dtd
suite/themes/classic/communicator/certError.css
suite/themes/modern/communicator/certError.css
--- a/suite/base/content/certError.js
+++ b/suite/base/content/certError.js
@@ -22,35 +22,66 @@ document.getElementById("technicalConten
 document.getElementById("expertContentHeading")
         .addEventListener("click", function() { toggle("expertContent"); });
 
 let gSearchParams;
 
 // Set to true on init if the error code is nssBadCert.
 let gIsCertError;
 
+// Set to true on init if a neterror.
+let gIsNetError;
+
 initPage();
 
 function getErrorCode() {
   return gSearchParams.get("e");
 }
 
 function getCSSClass() {
   return gSearchParams.get("s");
 }
 
 function getDescription() {
   return gSearchParams.get("d");
 }
 
+function retryThis(buttonEl) {
+  // Note: The application may wish to handle switching off "offline mode"
+  // before this event handler runs, but using a capturing event handler.
+
+  // Session history has the URL of the page that failed
+  // to load, not the one of the error page. So, just call
+  // reload(), which will also repost POST data correctly.
+  try {
+    location.reload();
+  } catch (e) {
+    // We probably tried to reload a URI that caused an exception to
+    // occur;  e.g. a nonexistent file.
+  }
+
+  buttonEl.disabled = true;
+}
+
 function initPage() {
   gSearchParams = new URLSearchParams(document.documentURI.split("?")[1]);
 
   let err = getErrorCode();
+  // List of neterror pages which have no error code and
+  // could have an illustration instead.
+  let illustratedErrors = [
+    "malformedURI", "dnsNotFound", "connectionFailure", "netInterrupt",
+    "netTimeout", "netReset", "netOffline",
+  ];
+  if (illustratedErrors.includes(err)) {
+    document.body.classList.add("illustrated", err);
+  }
+
   gIsCertError = (err == "nssBadCert");
+  gIsNetError = (document.documentURI.startsWith("about:neterror"));
 
   let pageTitle = document.getElementById("ept_" + err);
   if (pageTitle) {
     document.title = pageTitle.textContent;
   }
 
   // If it's an unknown error or there's no title or description defined,
   // get the generic message.
@@ -65,58 +96,112 @@ function initPage() {
   if (title) {
     title.innerHTML = errTitle.innerHTML;
   }
 
   let sd = document.getElementById("errorShortDescText");
   if (sd) {
     if (gIsCertError) {
       sd.innerHTML = errDesc.innerHTML;
+    } else if (!err || err == "unknownProtocolFound") {
+      sd.remove();
     } else {
-      sd.textContent = getDescription();
+      let desc = getDescription();
+      if (!illustratedErrors.includes(err) && gIsNetError) {
+        let codeRe = /<a id="errorCode" title="([^"]+)">/;
+        let codeResult = codeRe.exec(desc);
+        if (codeResult) {
+          let msg = desc.slice(0, codeResult.index) + codeResult[1];
+          sd.textContent = msg;
+          sd.className = "wrap";
+        } else {
+          sd.textContent = desc;
+        }
+      } else {
+        sd.textContent = desc;
+      }
     }
   }
 
   let xd = document.getElementById("errorShortDescExtra");
   if (xd) {
     let errExtra = document.getElementById("ex_" + err);
     if (gIsCertError && errExtra) {
       xd.innerHTML = errExtra.innerHTML;
     } else {
       xd.remove();
     }
   }
 
+  let ld = document.getElementById("errorLongDesc");
+  if (ld && !gIsCertError) {
+    ld.innerHTML = errDesc.innerHTML;
+  }
+
   // Remove undisplayed errors to avoid bug 39098.
   let errContainer = document.getElementById("errorContainer");
   errContainer.remove();
 
-  if (gIsCertError) {
+  if (gIsCertError || err == "inadequateSecurityError") {
     for (let host of document.querySelectorAll(".hostname")) {
       host.textContent = location.host;
     }
   }
 
+  if (gIsCertError || err == "sslv3Used") {
+    document.body.classList.add("certerror");
+  }
+
+  if (gIsCertError || err == "remoteXUL" || err == "cspBlocked" ||
+      err == "inadequateSecurityError") {
+    // Remove the "Try again" button for certificate errors, remote XUL errors,
+    // CSP violations (Bug 553180) and HTTP/2 inadequate security,
+    // given that it is useless.
+    document.getElementById("netErrorButtonContainer").style.display = "none";
+  }
+
   let className = getCSSClass();
+  if (className && className != "expertBadCert") {
+    // Associate a CSS class with the root of the page, if one was passed in,
+    // to allow custom styling.
+    // Not "expertBadCert" though, don't want to deal with the favicon
+    document.documentElement.classList.add(className);
+  }
+
   if (className == "expertBadCert") {
     toggle("technicalContent");
     toggle("expertContent");
   }
 
   // Disallow overrides if this is a Strict-Transport-Security
   // host and the cert is bad (STS Spec section 7.3);
   // or if the cert error is in a frame (bug 633691).
-  if (className == "badStsCert" || window != top) {
-    document.getElementById("expertContent").setAttribute("hidden", "true");
+  if (className == "badStsCert" || window != top || !gIsCertError) {
+    let expertContent = document.getElementById("expertContent");
+    expertContent.remove();
   }
   if (className == "badStsCert") {
     document.getElementById("badStsCertExplanation").removeAttribute("hidden");
   }
 
-  addDomainErrorLinks();
+  // For neterrors set a suitable class.
+  if (gIsNetError) {
+    document.body.classList.add("neterror");
+  }
+
+  // For neterrors and null error codes do not show the What Should I Do and
+  // Technical Details sections.
+  if (gIsNetError || !err) {
+    let whatShould = document.getElementById("whatShouldIDoContent");
+    whatShould.remove();
+    let technicalContent = document.getElementById("technicalContent");
+    technicalContent.remove();
+  } else {
+    addDomainErrorLinks();
+  }
 }
 
 /* In the case of SSL error pages about domain mismatch, see if
    we can hyperlink the user to the correct site.  We don't want
    to do this generically since it allows MitM attacks to redirect
    users to a site under attacker control, but in certain cases
    it is safe (and helpful!) to do so.  Bug 402210
 */
@@ -137,18 +222,18 @@ function addDomainErrorLinks() {
   var domainRe = /<a id="cert_domain_link" title="([^"]+)">/;
   var domainResult = domainRe.exec(desc);
   // The order of these links in the description is fixed in
   // TransportSecurityInfo.cpp:formatOverridableCertErrorMessage.
   var firstResult = domainResult;
   if (!domainResult)
     firstResult = codeResult;
   if (!firstResult) {
-      sd.textContent = desc;
-      return;
+    sd.textContent = desc;
+    return;
   }
 
   // Remove sd's existing children.
   sd.textContent = "";
 
   // Everything up to the link should be text content.
   sd.appendChild(document.createTextNode(desc.slice(0, firstResult.index)));
 
--- a/suite/base/content/certError.xhtml
+++ b/suite/base/content/certError.xhtml
@@ -29,25 +29,73 @@
   </head>
 
   <body dir="&locale.dir;">
 
     <!-- ERROR ITEM CONTAINER (removed during loading to avoid bug 39098) -->
     <div id="errorContainer" style="display: none;">
       <div id="errorPageTitlesContainer">
         <span id="ept_nssBadCert">&certerror.pagetitle;</span>
+        <span id="ept_dnsNotFound">&dnsNotFound.pageTitle;</span>
+        <span id="ept_malformedURI">&malformedURI.pageTitle;</span>
       </div>
       <div id="errorTitlesContainer">
         <h1 id="et_generic">&generic.title;</h1>
+        <h1 id="et_dnsNotFound">&dnsNotFound.title;</h1>
+        <h1 id="et_fileNotFound">&fileNotFound.title;</h1>
+        <h1 id="et_fileAccessDenied">&fileAccessDenied.title;</h1>
+        <h1 id="et_malformedURI">&malformedURI.title;</h1>
+        <h1 id="et_unknownProtocolFound">&unknownProtocolFound.title;</h1>
+        <h1 id="et_connectionFailure">&connectionFailure.title;</h1>
+        <h1 id="et_netTimeout">&netTimeout.title;</h1>
+        <h1 id="et_redirectLoop">&redirectLoop.title;</h1>
+        <h1 id="et_unknownSocketType">&unknownSocketType.title;</h1>
+        <h1 id="et_netReset">&netReset.title;</h1>
+        <h1 id="et_notCached">&notCached.title;</h1>
+        <h1 id="et_netOffline">&netOffline.title;</h1>
+        <h1 id="et_netInterrupt">&netInterrupt.title;</h1>
+        <h1 id="et_deniedPortAccess">&deniedPortAccess.title;</h1>
+        <h1 id="et_proxyResolveFailure">&proxyResolveFailure.title;</h1>
+        <h1 id="et_proxyConnectFailure">&proxyConnectFailure.title;</h1>
+        <h1 id="et_contentEncodingError">&contentEncodingError.title;</h1>
+        <h1 id="et_unsafeContentType">&unsafeContentType.title;</h1>
+        <h1 id="et_nssFailure2">&nssFailure2.title;</h1>
         <h1 id="et_nssBadCert">&certerror.longpagetitle;</h1>
+        <h1 id="et_cspBlocked">&cspBlocked.title;</h1>
+        <h1 id="et_remoteXUL">&remoteXUL.title;</h1>
+        <h1 id="et_corruptedContentErrorv2">&corruptedContentErrorv2.title;</h1>
+        <h1 id="et_inadequateSecurityError">&inadequateSecurityError.title;</h1>
       </div>
       <div id="errorDescriptionsContainer">
         <div id="ed_generic">&generic.longDesc;</div>
+        <div id="ed_dnsNotFound">&dnsNotFound.longDesc;</div>
+        <div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
+        <div id="ed_fileAccessDenied">&fileAccessDenied.longDesc;</div>
+        <div id="ed_malformedURI">&malformedURI.longDesc;</div>
+        <div id="ed_unknownProtocolFound">&unknownProtocolFound.longDesc;</div>
+        <div id="ed_connectionFailure">&connectionFailure.longDesc;</div>
+        <div id="ed_netTimeout">&netTimeout.longDesc;</div>
+        <div id="ed_redirectLoop">&redirectLoop.longDesc;</div>
+        <div id="ed_unknownSocketType">&unknownSocketType.longDesc;</div>
+        <div id="ed_netReset">&netReset.longDesc;</div>
+        <div id="ed_notCached">&notCached.longDesc;</div>
+        <div id="ed_netOffline">&netOffline.longDesc2;</div>
+        <div id="ed_netInterrupt">&netInterrupt.longDesc;</div>
+        <div id="ed_deniedPortAccess">&deniedPortAccess.longDesc;</div>
+        <div id="ed_proxyResolveFailure">&proxyResolveFailure.longDesc;</div>
+        <div id="ed_proxyConnectFailure">&proxyConnectFailure.longDesc;</div>
+        <div id="ed_contentEncodingError">&contentEncodingError.longDesc;</div>
+        <div id="ed_unsafeContentType">&unsafeContentType.longDesc;</div>
+        <div id="ed_nssFailure2">&nssFailure2.longDesc2;</div>
         <div id="ed_nssBadCert">&certerror.introPara1a;</div>
         <div id="ex_nssBadCert">&certerror.introPara2;</div>
+        <div id="ed_cspBlocked">&cspBlocked.longDesc;</div>
+        <div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
+        <div id="ed_corruptedContentErrorv2">&corruptedContentErrorv2.longDesc;</div>
+        <div id="ed_inadequateSecurityError">&inadequateSecurityError.longDesc;</div>
       </div>
     </div>
 
     <!-- PAGE CONTAINER (for styling purposes only) -->
     <div id="errorPageContainer">
 
       <!-- Error Title -->
       <div id="errorTitle">
@@ -58,16 +106,19 @@
       <div id="errorLongContent">
 
         <!-- Short Description -->
         <div id="errorShortDesc">
           <p id="errorShortDescText"/>
           <p id="errorShortDescExtra"/>
         </div>
 
+        <!-- Long Description (Note: See netError.dtd for used XHTML tags) -->
+        <div id="errorLongDesc"/>
+
         <div id="whatShouldIDoContent">
           <h2>&certerror.whatShouldIDo.heading;</h2>
           <div id="whatShouldIDoContentText">
             <p>&certerror.whatShouldIDo.content;</p>
             <p id="badStsCertExplanation"
                hidden="true">&certerror.whatShouldIDo.badStsCertExplanation;</p>
             <span id="getMeOutOfHereButton"
                   class="button"
@@ -87,16 +138,23 @@
           <div>
             <p>&certerror.expert.content;</p>
             <p>&certerror.expert.contentPara2;</p>
             <span id="exceptionDialogButton"
                   class="button"
                   label="&certerror.addException.label;"/>
           </div>
         </div>
+
+        <div id="netErrorButtonContainer" class="button-container">
+          <button id="errorTryAgain"
+                  class="primary"
+                  autocomplete="off"
+                  onclick="retryThis(this);">&retry.label;</button>
+        </div>
       </div>
     </div>
 
     <!--
     - Note: It is important to run the script this way, instead of using
     - a window.onload function. This is because error pages are loaded as
     - LOAD_BACKGROUND, which means that onload handlers will not be executed.
     -->
--- a/suite/base/jar.mn
+++ b/suite/base/jar.mn
@@ -2,16 +2,17 @@
 
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.comm.jar:
 
 comm.jar:
 % content communicator %content/communicator/ contentaccessible=yes
 % override chrome://global/content/license.html chrome://communicator/content/license.html
+% override chrome://global/content/netError.xhtml chrome://communicator/content/certError.xhtml
 % overlay chrome://global/content/viewSource.xul chrome://communicator/content/viewSourceOverlay.xul
 % overlay chrome://global/content/viewPartialSource.xul chrome://communicator/content/viewSourceOverlay.xul
 % overlay chrome://editor/content/EdAdvancedEdit.xul chrome://communicator/content/helpEditorOverlay.xul
 % overlay chrome://editor/content/EdImageProps.xul chrome://communicator/content/helpEditorOverlay.xul
 % overlay chrome://editor/content/EditorPublish.xul chrome://communicator/content/helpEditorOverlay.xul
 % overlay chrome://editor/content/EditorPublishProgress.xul chrome://communicator/content/helpEditorOverlay.xul
 % overlay chrome://editor/content/EditorPublishSettings.xul chrome://communicator/content/helpEditorOverlay.xul
 % overlay chrome://editor/content/EdLinkProps.xul chrome://communicator/content/helpEditorOverlay.xul
--- a/suite/locales/en-US/chrome/common/certError.dtd
+++ b/suite/locales/en-US/chrome/common/certError.dtd
@@ -34,8 +34,11 @@ certificate.">
 can tell &brandShortName; to start trusting this website's identification.
 <b>Even if you trust the website, this error could mean that someone is
 tampering with your connection.</b>">
 <!ENTITY certerror.expert.contentPara2 "Don't add an exception unless
 you know there's a good reason why this website doesn't use trusted identification.">
 <!ENTITY certerror.addException.label "Add Exception…">
 
 <!ENTITY certerror.technical.heading "Technical Details">
+
+<!ENTITY dnsNotFound.pageTitle "Server Not Found">
+<!ENTITY malformedURI.pageTitle "Invalid URL">
--- a/suite/themes/classic/communicator/certError.css
+++ b/suite/themes/classic/communicator/certError.css
@@ -48,16 +48,20 @@ body[dir="rtl"] #errorPageContainer {
 #errorTitle {
   margin-inline-start: 80px;
 }
 
 #errorLongContent {
   margin-inline-start: 80px;
 }
 
+#errorShortDescText.wrap {
+  white-space: pre-wrap;
+}
+
 #technicalContent > h2, #expertContent > h2 {
   cursor: pointer;
   padding-inline-start: 20px;
   position: relative;
   left: -20px;
   background: url("chrome://messenger/skin/icons/twisty-open.png") left center no-repeat;
 }
 
--- a/suite/themes/modern/communicator/certError.css
+++ b/suite/themes/modern/communicator/certError.css
@@ -48,16 +48,20 @@ body[dir="rtl"] #errorPageContainer {
 #errorTitle {
   margin-inline-start: 80px;
 }
 
 #errorLongContent {
   margin-inline-start: 80px;
 }
 
+#errorShortDescText.wrap {
+  white-space: pre-wrap;
+}
+
 #technicalContent > h2, #expertContent > h2 {
   cursor: pointer;
   padding-inline-start: 20px;
   position: relative;
   left: -20px;
   background: url("chrome://global/skin/tree/twisty-open.gif") left center no-repeat;
 }