diff options
Diffstat (limited to 'toolkit/components/httpsonlyerror/content')
3 files changed, 211 insertions, 0 deletions
diff --git a/toolkit/components/httpsonlyerror/content/errorpage.html b/toolkit/components/httpsonlyerror/content/errorpage.html new file mode 100644 index 0000000000..4f2c62f49a --- /dev/null +++ b/toolkit/components/httpsonlyerror/content/errorpage.html @@ -0,0 +1,78 @@ +<!-- 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/. --> + +<!DOCTYPE html> + +<html> + <head> + <meta + http-equiv="Content-Security-Policy" + content="default-src chrome:; object-src 'none'" + /> + <meta name="color-scheme" content="light dark" /> + <link + rel="stylesheet" + href="chrome://global/skin/in-content/info-pages.css" + /> + <link + rel="stylesheet" + href="chrome://global/skin/aboutHttpsOnlyError.css" + /> + <link rel="localization" href="branding/brand.ftl" /> + <link rel="localization" href="toolkit/about/aboutHttpsOnlyError.ftl" /> + <!-- If the location of the favicon is changed here, the FAVICON_ERRORPAGE_URL symbol in + toolkit/components/places/src/nsFaviconService.h should be updated. --> + <link rel="icon" id="favicon" href="chrome://global/skin/icons/info.svg" /> + <title data-l10n-id="about-httpsonly-title-site-not-available"></title> + </head> + <body> + <main class="container"> + <div class="title"> + <h2 data-l10n-id="about-httpsonly-title-alert"></h2> + <h1 + class="title-text" + data-l10n-id="about-httpsonly-title-site-not-available" + ></h1> + </div> + <p + id="insecure-explanation-unavailable" + data-l10n-id="about-httpsonly-explanation-unavailable2" + data-l10n-args='{"websiteUrl": ""}' + ></p> + <p id="learn-more-container"> + <a + id="learnMoreLink" + target="_blank" + data-l10n-id="about-httpsonly-link-learn-more" + ></a> + </p> + + <b data-l10n-id="about-httpsonly-explanation-question"></b> + <ul> + <li data-l10n-id="about-httpsonly-explanation-nosupport"></li> + <li data-l10n-id="about-httpsonly-explanation-risk"></li> + </ul> + + <p + id="explanation-continue" + data-l10n-id="about-httpsonly-explanation-continue" + ></p> + <div class="button-container"> + <button + id="goBack" + class="primary" + data-l10n-id="about-httpsonly-button-go-back" + ></button> + <button + id="openInsecure" + data-l10n-id="about-httpsonly-button-continue-to-site" + ></button> + </div> + <div class="suggestion-box" hidden> + <h2 data-l10n-id="about-httpsonly-suggestion-box-header"></h2> + </div> + </main> + <script src="chrome://global/content/httpsonlyerror/errorpage.js"></script> + </body> +</html> diff --git a/toolkit/components/httpsonlyerror/content/errorpage.js b/toolkit/components/httpsonlyerror/content/errorpage.js new file mode 100644 index 0000000000..cfd9458d53 --- /dev/null +++ b/toolkit/components/httpsonlyerror/content/errorpage.js @@ -0,0 +1,129 @@ +/* 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/. */ + +/* eslint-env mozilla/remote-page */ + +"use strict"; + +const searchParams = new URLSearchParams(document.documentURI.split("?")[1]); + +function initPage() { + if (!searchParams.get("e")) { + document.getElementById("error").remove(); + } + + const explanation1 = document.getElementById( + "insecure-explanation-unavailable" + ); + + const pageUrl = new URL(window.location.href.replace(/^view-source:/, "")); + + document.l10n.setAttributes( + explanation1, + "about-httpsonly-explanation-unavailable2", + { websiteUrl: pageUrl.host } + ); + + const baseSupportURL = RPMGetFormatURLPref("app.support.baseURL"); + document + .getElementById("learnMoreLink") + .setAttribute("href", baseSupportURL + "https-only-prefs"); + + document + .getElementById("openInsecure") + .addEventListener("click", onOpenInsecureButtonClick); + + if (window.top == window) { + document + .getElementById("goBack") + .addEventListener("click", onReturnButtonClick); + addAutofocus("#goBack", "beforeend"); + } else { + document.getElementById("goBack").remove(); + } + + const isTopLevel = window.top == window; + const hasWWWPrefix = pageUrl.href.startsWith("https://www."); + if (isTopLevel && !hasWWWPrefix) { + // HTTPS-Only generally simply replaces http: with https:; + // here we additionally try to add www and see if that allows to upgrade the connection if it is top level + + window.addEventListener("pingSecureWWWLinkSuccess", () => { + activateSuggestionBox(); + displayWWWSuggestion(pageUrl.host); + }); + + // try to ping secure www link in the AboutHttpsOnlyErrorChild + RPMTryPingSecureWWWLink(); + } +} + +/* Suggestion Box */ + +function activateSuggestionBox() { + const suggestionBox = document.querySelector(".suggestion-box"); + suggestionBox.hidden = false; +} + +function displayWWWSuggestion(aURL) { + const suggestionBox = document.querySelector(".suggestion-box"); + const suggestionWWWText = document.createElement("p"); + const suggestionWWWButton = document.createElement("button"); + const suggestionButtonContainer = document.createElement("div"); + + document.l10n.setAttributes( + suggestionWWWText, + "about-httpsonly-suggestion-box-www-text", + { websiteUrl: aURL } + ); + + suggestionWWWButton.setAttribute("id", "openWWW"); + document.l10n.setAttributes( + suggestionWWWButton, + "about-httpsonly-suggestion-box-www-button", + { websiteUrl: aURL } + ); + suggestionWWWButton.addEventListener("click", openSecureWWWButtonClick); + + suggestionButtonContainer.classList.add("button-container"); + + suggestionBox.appendChild(suggestionWWWText); + suggestionButtonContainer.appendChild(suggestionWWWButton); + suggestionBox.appendChild(suggestionButtonContainer); +} + +/* Button Events */ + +function openSecureWWWButtonClick() { + RPMOpenSecureWWWLink(); +} + +function onOpenInsecureButtonClick() { + document.reloadWithHttpsOnlyException(); +} + +function onReturnButtonClick() { + RPMSendAsyncMessage("goBack"); +} + +/* Utils */ + +function addAutofocus(selector, position = "afterbegin") { + if (window.top != window) { + return; + } + var button = document.querySelector(selector); + var parent = button.parentNode; + button.remove(); + button.setAttribute("autofocus", "true"); + parent.insertAdjacentElement(position, button); +} + +/* Initialize Page */ + +initPage(); +// Dispatch this event so tests can detect that we finished loading the error page. +// We're using the same event name as neterror because BrowserTestUtils.sys.mjs relies on that. +let event = new CustomEvent("AboutNetErrorLoad", { bubbles: true }); +document.dispatchEvent(event); diff --git a/toolkit/components/httpsonlyerror/content/secure-broken.svg b/toolkit/components/httpsonlyerror/content/secure-broken.svg new file mode 100644 index 0000000000..417d17b3cc --- /dev/null +++ b/toolkit/components/httpsonlyerror/content/secure-broken.svg @@ -0,0 +1,4 @@ +<!-- 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/. --> +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="context-fill #424e5a"><path d="M18.75 9.977h-.727L6 22h12.75A2.25 2.25 0 0 0 21 19.75v-7.523a2.25 2.25 0 0 0-2.25-2.25zm-9.75 0V7a3 3 0 0 1 6 0v1.5l2.838-2.838A5.994 5.994 0 0 0 6 7v2.977h-.75A2.25 2.25 0 0 0 3 12.227v7.523a2.224 2.224 0 0 0 .105.645L13.523 9.977z"></path><path d="M2.5 23a1.5 1.5 0 0 1-1.061-2.561l19-19A1.5 1.5 0 0 1 22.56 3.56l-19 19A1.5 1.5 0 0 1 2.5 23z" fill="#ff0039"></path></svg> |