зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1596845
- Make custom about:neterror page for TRR mode3 DNS failures r=pbz,fluent-reviewers,settings-reviewers,flod,edgul
This changes about:neterror to show a specific error page when the DNS failure occurs for a TRR mode3 page load. This offers the user more information about the failure, and some options. This page will be further improved at a later stage when we add a better DNS over HTTPS settings page. The page is visible when the browser is using DNS over HTTPS without fallback to native DNS. To achieve this the user sets `network.trr.mode` to `3` then loads a page such as `http://nonexistant.test`. If a top level load's channel returns NS_ERROR_UNKNOWN_HOST we look at whether the page was indeed loaded with an effectiveTRRMode == TRRONLY (some loads are excluded from using TRR). When that is true, we present the error page allowing the user to retry, exclude the domain from TRR, or open the settings page. Note: This initial implementation will not work if the `network.dns.disablePrefetch` pref is set to true. In that case nsHttpChannel does not get an OnLookupComplete callback, so it doesn't have the effectiveTRRMode and trrSkipReason. This will be fixed in bug 1805372. Project plan: https://docs.google.com/document/d/12IGABt1eXI276qHduXXbVZqRFrhLN7Ad3gKEgxz81sE Copy deck: https://docs.google.com/document/d/130UTox8bQbybjYIwvltR4qBg2hWjsGhuNUHypLwUAEQ Depends on D164642 Differential Revision: https://phabricator.services.mozilla.com/D164347
This commit is contained in:
Родитель
b47ce8d43f
Коммит
1fe810288f
|
@ -753,7 +753,8 @@
|
|||
<groupbox id="connectionGroup" data-category="paneGeneral" hidden="true">
|
||||
<label class="search-header" hidden="true"><html:h2 data-l10n-id="network-settings-title"/></label>
|
||||
|
||||
<hbox align="center">
|
||||
<hbox align="center"
|
||||
data-subcategory="netsettings">
|
||||
<description flex="1" control="connectionSettings">
|
||||
<html:span id="connectionSettingsDescription"/>
|
||||
<label id="connectionSettingsLearnMore" class="learnMore" is="text-link" data-l10n-id="network-proxy-connection-learn-more"/>
|
||||
|
|
|
@ -11733,6 +11733,12 @@
|
|||
value: false
|
||||
mirror: always
|
||||
|
||||
# The base URL of the `Learn more` button for skip reasons
|
||||
- name: network.trr_ui.skip_reason_learn_more_url
|
||||
type: String
|
||||
value: "https://firefox-source-docs.mozilla.org/networking/dns/trr-skip-reasons.html#"
|
||||
mirror: never
|
||||
|
||||
# Allow the network changed event to get sent when a network topology or setup
|
||||
# change is noticed while running.
|
||||
- name: network.notify.changed
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
|
||||
var EXPORTED_SYMBOLS = ["NetErrorChild"];
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
AppInfo: "chrome://remote/content/shared/AppInfo.sys.mjs",
|
||||
});
|
||||
|
||||
const { RemotePageChild } = ChromeUtils.import(
|
||||
"resource://gre/actors/RemotePageChild.jsm"
|
||||
);
|
||||
|
@ -22,6 +28,11 @@ class NetErrorChild extends RemotePageChild {
|
|||
"RPMRecordTelemetryEvent",
|
||||
"RPMCheckAlternateHostAvailable",
|
||||
"RPMGetHttpResponseHeader",
|
||||
"RPMIsTRROnlyFailure",
|
||||
"RPMShowTRROnlyFailureError",
|
||||
"RPMOpenPreferences",
|
||||
"RPMGetTRRSkipReason",
|
||||
"RPMGetTRRDomain",
|
||||
];
|
||||
this.exportFunctions(exportableFunctions);
|
||||
}
|
||||
|
@ -149,4 +160,31 @@ class NetErrorChild extends RemotePageChild {
|
|||
|
||||
return "";
|
||||
}
|
||||
|
||||
RPMIsTRROnlyFailure() {
|
||||
// As per RPMShowTRROnlyFailureError, we will only show this in Firefox
|
||||
let channel = this.contentWindow?.docShell?.failedChannel?.QueryInterface(
|
||||
Ci.nsIHttpChannelInternal
|
||||
);
|
||||
if (!channel) {
|
||||
return false;
|
||||
}
|
||||
return channel.effectiveTRRMode == Ci.nsIRequest.TRR_ONLY_MODE;
|
||||
}
|
||||
|
||||
RPMShowTRROnlyFailureError() {
|
||||
return lazy.AppInfo.isFirefox;
|
||||
}
|
||||
|
||||
RPMGetTRRSkipReason() {
|
||||
let channel = this.contentWindow?.docShell?.failedChannel?.QueryInterface(
|
||||
Ci.nsIHttpChannelInternal
|
||||
);
|
||||
let value = channel?.trrSkipReason ?? Ci.nsITRRSkipReason.TRR_UNSET;
|
||||
return Services.dns.getTRRSkipReasonName(value);
|
||||
}
|
||||
|
||||
RPMGetTRRDomain() {
|
||||
return Services.dns.trrDomain;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -329,6 +329,30 @@ class NetErrorParent extends JSWindowActorParent {
|
|||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "Browser:AddTRRExcludedDomain":
|
||||
let domain = message.data.hostname;
|
||||
let excludedDomains = Services.prefs.getStringPref(
|
||||
"network.trr.excluded-domains"
|
||||
);
|
||||
excludedDomains += `, ${domain}`;
|
||||
Services.prefs.setStringPref(
|
||||
"network.trr.excluded-domains",
|
||||
excludedDomains
|
||||
);
|
||||
break;
|
||||
case "OpenTRRPreferences":
|
||||
let browser = this.browsingContext.top.embedderElement;
|
||||
if (!browser) {
|
||||
break;
|
||||
}
|
||||
|
||||
let win = browser.ownerGlobal;
|
||||
// XXX(valentin) This will be a different section
|
||||
// when we move DNS over HTTPS settings to the privacy page
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1610741
|
||||
win.openPreferences("general-netsettings");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ const KNOWN_ERROR_TITLE_IDS = new Set([
|
|||
"connectionFailure-title",
|
||||
"deniedPortAccess-title",
|
||||
"dnsNotFound-title",
|
||||
"dns-not-found-trr-only-title",
|
||||
"fileNotFound-title",
|
||||
"fileAccessDenied-title",
|
||||
"generic-title",
|
||||
|
@ -236,6 +237,8 @@ function initPage() {
|
|||
document.body.classList.add(className);
|
||||
}
|
||||
|
||||
const isTRROnlyFailure = gErrorCode == "dnsNotFound" && RPMIsTRROnlyFailure();
|
||||
|
||||
const docTitle = document.querySelector("title");
|
||||
const bodyTitle = document.querySelector(".title-text");
|
||||
const shortDesc = document.getElementById("errorShortDesc");
|
||||
|
@ -329,9 +332,11 @@ function initPage() {
|
|||
|
||||
case "dnsNotFound":
|
||||
pageTitleId = "neterror-dns-not-found-title";
|
||||
RPMCheckAlternateHostAvailable();
|
||||
break;
|
||||
if (!isTRROnlyFailure) {
|
||||
RPMCheckAlternateHostAvailable();
|
||||
}
|
||||
|
||||
break;
|
||||
case "inadequateSecurityError":
|
||||
// Remove the "Try again" button from pages that don't need it.
|
||||
// For HTTP/2 inadequate security, trying again won't help.
|
||||
|
@ -380,16 +385,101 @@ function initPage() {
|
|||
break;
|
||||
}
|
||||
|
||||
document.l10n.setAttributes(docTitle, pageTitleId);
|
||||
|
||||
if (!KNOWN_ERROR_TITLE_IDS.has(bodyTitleId)) {
|
||||
console.error("No strings exist for error:", gErrorCode);
|
||||
bodyTitleId = "generic-title";
|
||||
}
|
||||
|
||||
if (isTRROnlyFailure && RPMShowTRROnlyFailureError()) {
|
||||
document.body.className = "certerror"; // Shows warning icon
|
||||
pageTitleId = "dns-not-found-trr-only-title";
|
||||
document.l10n.setAttributes(docTitle, pageTitleId, {
|
||||
hostname: HOST_NAME,
|
||||
});
|
||||
bodyTitleId = "dns-not-found-trr-only-title";
|
||||
document.l10n.setAttributes(bodyTitle, bodyTitleId, {
|
||||
hostname: HOST_NAME,
|
||||
});
|
||||
|
||||
shortDesc.textContent = "";
|
||||
|
||||
// enable buttons
|
||||
let trrExceptionButton = document.getElementById("trrExceptionButton");
|
||||
trrExceptionButton.addEventListener("click", () => {
|
||||
RPMSendQuery("Browser:AddTRRExcludedDomain", {
|
||||
hostname: HOST_NAME,
|
||||
}).then(msg => {
|
||||
retryThis(this);
|
||||
});
|
||||
});
|
||||
trrExceptionButton.hidden = false;
|
||||
let trrSettingsButton = document.getElementById("trrSettingsButton");
|
||||
trrSettingsButton.addEventListener("click", () => {
|
||||
RPMSendAsyncMessage("OpenTRRPreferences");
|
||||
});
|
||||
trrSettingsButton.hidden = false;
|
||||
let message = document.getElementById("trrOnlyMessage");
|
||||
document.l10n.setAttributes(
|
||||
message,
|
||||
"neterror-dns-not-found-trr-only-reason",
|
||||
{
|
||||
hostname: HOST_NAME,
|
||||
}
|
||||
);
|
||||
|
||||
let skipReason = RPMGetTRRSkipReason();
|
||||
|
||||
let descriptionTag = "neterror-dns-not-found-trr-unknown-problem";
|
||||
let args = { trrDomain: RPMGetTRRDomain() };
|
||||
if (
|
||||
skipReason == "TRR_FAILED" ||
|
||||
skipReason == "TRR_CHANNEL_DNS_FAIL" ||
|
||||
skipReason == "TRR_UNKNOWN_CHANNEL_FAILURE" ||
|
||||
skipReason == "TRR_NET_REFUSED" ||
|
||||
skipReason == "TRR_NET_INTERRUPT" ||
|
||||
skipReason == "TRR_NET_INADEQ_SEQURITY"
|
||||
) {
|
||||
descriptionTag = "neterror-dns-not-found-trr-only-could-not-connect";
|
||||
} else if (skipReason == "TRR_TIMEOUT") {
|
||||
descriptionTag = "neterror-dns-not-found-trr-only-timeout";
|
||||
} else if (
|
||||
skipReason == "TRR_IS_OFFLINE" ||
|
||||
skipReason == "TRR_NO_CONNECTIVITY"
|
||||
) {
|
||||
descriptionTag = "neterror-dns-not-found-trr-offline";
|
||||
} else if (skipReason == "TRR_NO_ANSWERS" || skipReason == "TRR_NXDOMAIN") {
|
||||
descriptionTag = "neterror-dns-not-found-trr-unknown-host";
|
||||
} else if (
|
||||
skipReason == "TRR_DECODE_FAILED" ||
|
||||
skipReason == "TRR_SERVER_RESPONSE_ERR"
|
||||
) {
|
||||
descriptionTag = "neterror-dns-not-found-trr-server-problem";
|
||||
}
|
||||
|
||||
let description = document.getElementById("trrOnlyDescription");
|
||||
document.l10n.setAttributes(description, descriptionTag, args);
|
||||
|
||||
const trrLearnMoreContainer = document.getElementById(
|
||||
"trrLearnMoreContainer"
|
||||
);
|
||||
trrLearnMoreContainer.hidden = false;
|
||||
let learnMoreLink = document.getElementById("trrOnlylearnMoreLink");
|
||||
// This will be replaced at a later point with a link to an offline support page
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1806257
|
||||
learnMoreLink.href =
|
||||
RPMGetFormatURLPref("network.trr_ui.skip_reason_learn_more_url") +
|
||||
skipReason.toLowerCase().replaceAll("_", "-");
|
||||
|
||||
let div = document.getElementById("trrOnlyContainer");
|
||||
div.hidden = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
document.l10n.setAttributes(docTitle, pageTitleId);
|
||||
document.l10n.setAttributes(bodyTitle, bodyTitleId);
|
||||
|
||||
shortDesc.textContent = getDescription();
|
||||
|
||||
setFocus("#netErrorButtonContainer > .try-again");
|
||||
|
||||
if (longDesc) {
|
||||
|
|
|
@ -40,6 +40,17 @@
|
|||
<!-- Long Description -->
|
||||
<div id="errorLongDesc"></div>
|
||||
|
||||
<p id="trrOnlyContainer" hidden="">
|
||||
<p id="trrOnlyMessage"></p>
|
||||
<div class="trr-message-container">
|
||||
<span id="trrOnlyDescription"></span>
|
||||
<p id="trrLearnMoreContainer" hidden="">
|
||||
<a id="trrOnlylearnMoreLink" target="_blank" rel="noopener noreferrer" data-l10n-id="neterror-learn-more-link"></a>
|
||||
</p>
|
||||
</div>
|
||||
<p data-l10n-id="neterror-dns-not-found-trr-only-attackers"> </p>
|
||||
</p>
|
||||
|
||||
<p id="tlsVersionNotice" hidden=""></p>
|
||||
|
||||
<p id="learnMoreContainer" hidden="">
|
||||
|
@ -68,6 +79,8 @@
|
|||
|
||||
<div id="netErrorButtonContainer" class="button-container" hidden="">
|
||||
<button class="primary try-again" data-l10n-id="neterror-try-again-button"></button>
|
||||
<button id="trrExceptionButton" data-l10n-id="neterror-add-exception-button" hidden=""></button>
|
||||
<button id="trrSettingsButton" data-l10n-id="neterror-settings-button" hidden=""></button>
|
||||
</div>
|
||||
|
||||
<div class="advanced-panel-container">
|
||||
|
|
|
@ -104,6 +104,12 @@ deniedPortAccess-title = This address is restricted
|
|||
# "Hmm" is a sound made when considering or puzzling over something.
|
||||
# You don't have to include it in your translation if your language does not have a written word like this.
|
||||
dnsNotFound-title = Hmm. We’re having trouble finding that site.
|
||||
|
||||
# Variables:
|
||||
# $hostname (String) - Hostname of the website to which the user was trying to connect.
|
||||
dns-not-found-trr-only-title =
|
||||
Possible security risk for { $hostname }.
|
||||
|
||||
fileNotFound-title = File not found
|
||||
fileAccessDenied-title = Access to the file was denied
|
||||
generic-title = Oops.
|
||||
|
|
|
@ -23,6 +23,8 @@ neterror-pref-reset-button = Restore default settings
|
|||
neterror-return-to-previous-page-button = Go Back
|
||||
neterror-return-to-previous-page-recommended-button = Go Back (Recommended)
|
||||
neterror-try-again-button = Try Again
|
||||
neterror-add-exception-button = Always continue for this site
|
||||
neterror-settings-button = Change DNS settings
|
||||
neterror-view-certificate-link = View Certificate
|
||||
|
||||
##
|
||||
|
@ -48,6 +50,23 @@ neterror-dns-not-found-hint-try-again = Try again later
|
|||
neterror-dns-not-found-hint-check-network = Check your network connection
|
||||
neterror-dns-not-found-hint-firewall = Check that { -brand-short-name } has permission to access the web (you might be connected but behind a firewall)
|
||||
|
||||
## TRR-only specific messages
|
||||
## Variables:
|
||||
## $hostname (String) - Hostname of the website to which the user was trying to connect.
|
||||
## $trrDomain (String) - Hostname of the DNS over HTTPS server that is currently in use.
|
||||
|
||||
neterror-dns-not-found-trr-only-reason = { -brand-short-name } can’t protect your request for this site’s address through our trusted DNS resolver. Here’s why:
|
||||
neterror-dns-not-found-trr-only-attackers = If you continue, a third-party might be able to see what websites you visit or send you to an untrusted site.
|
||||
|
||||
neterror-dns-not-found-trr-only-could-not-connect = { -brand-short-name } wasn’t able to connect to { $trrDomain }.
|
||||
neterror-dns-not-found-trr-only-timeout = The connection to { $trrDomain } took longer than expected.
|
||||
neterror-dns-not-found-trr-offline = You are not connected to the internet.
|
||||
neterror-dns-not-found-trr-unknown-host = An address for this website wasn’t found by { $trrDomain }.
|
||||
neterror-dns-not-found-trr-server-problem = There was a problem with { $trrDomain }.
|
||||
neterror-dns-not-found-trr-unknown-problem = Unexpected problem.
|
||||
|
||||
##
|
||||
|
||||
neterror-file-not-found-filename = Check the file name for capitalization or other typing errors.
|
||||
neterror-file-not-found-moved = Check to see if the file was moved, renamed or deleted.
|
||||
|
||||
|
|
|
@ -79,11 +79,15 @@ export let RemotePageAccessManager = {
|
|||
"Browser:ResetEnterpriseRootsPref",
|
||||
"ReportBlockingError",
|
||||
"DisplayOfflineSupportPage",
|
||||
"OpenTRRPreferences",
|
||||
],
|
||||
RPMCheckAlternateHostAvailable: ["*"],
|
||||
RPMAddMessageListener: ["*"],
|
||||
RPMRemoveMessageListener: ["*"],
|
||||
RPMGetFormatURLPref: ["app.support.baseURL"],
|
||||
RPMGetFormatURLPref: [
|
||||
"app.support.baseURL",
|
||||
"network.trr_ui.skip_reason_learn_more_url",
|
||||
],
|
||||
RPMGetBoolPref: [
|
||||
"security.certerror.hideAddException",
|
||||
"security.xfocsp.errorReporting.automatic",
|
||||
|
@ -93,6 +97,11 @@ export let RemotePageAccessManager = {
|
|||
RPMAddToHistogram: ["*"],
|
||||
RPMGetInnerMostURI: ["*"],
|
||||
RPMGetHttpResponseHeader: ["*"],
|
||||
RPMIsTRROnlyFailure: ["*"],
|
||||
RPMShowTRROnlyFailureError: ["*"],
|
||||
RPMGetTRRSkipReason: ["*"],
|
||||
RPMGetTRRDomain: ["*"],
|
||||
RPMSendQuery: ["Browser:AddTRRExcludedDomain"],
|
||||
},
|
||||
"about:plugins": {
|
||||
RPMSendQuery: ["RequestPlugins"],
|
||||
|
|
|
@ -85,7 +85,7 @@ button:disabled {
|
|||
display: flex;
|
||||
}
|
||||
|
||||
#netErrorButtonContainer > .try-again {
|
||||
#netErrorButtonContainer > button {
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,13 @@ button:disabled {
|
|||
left: 0;
|
||||
}
|
||||
|
||||
.trr-message-container {
|
||||
background-color: var(--in-content-box-background);
|
||||
border: 1px solid var(--in-content-box-border-color);
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#badCertAdvancedPanel {
|
||||
background-color: var(--in-content-box-background);
|
||||
border: 1px solid var(--in-content-box-border-color);
|
||||
|
|
|
@ -12,6 +12,7 @@ module.exports = {
|
|||
globals: {
|
||||
atob: false,
|
||||
btoa: false,
|
||||
RPMAddTRRExcludedDomain: false,
|
||||
RPMGetAppBuildID: false,
|
||||
RPMGetInnerMostURI: false,
|
||||
RPMGetIntPref: false,
|
||||
|
@ -19,6 +20,8 @@ module.exports = {
|
|||
RPMGetBoolPref: false,
|
||||
RPMSetBoolPref: false,
|
||||
RPMGetFormatURLPref: false,
|
||||
RPMIsTRROnlyFailure: false,
|
||||
RPMShowTRROnlyFailureError: false,
|
||||
RPMIsWindowPrivate: false,
|
||||
RPMSendAsyncMessage: false,
|
||||
RPMSendQuery: false,
|
||||
|
@ -30,5 +33,8 @@ module.exports = {
|
|||
RPMGetHttpResponseHeader: false,
|
||||
RPMTryPingSecureWWWLink: false,
|
||||
RPMOpenSecureWWWLink: false,
|
||||
RPMOpenPreferences: false,
|
||||
RPMGetTRRSkipReason: false,
|
||||
RPMGetTRRDomain: false,
|
||||
},
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче