The `dnsNotFound` error's customNetError config previously used a single `whatCanYouDoL10nId` pointing to a generic offline message. This patch replaces it with an array of three `l10n` ids that more accurately reflect what a user can do when DNS resolution fails: a general network hint, a check-network hint, and a firewall hint. I also added a test to check that the correct items are configured. Differential Revision: https://phabricator.services.mozilla.com/D300941
787 lines
22 KiB
JavaScript
787 lines
22 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
/**
|
|
* Tests for the error registry foundation.
|
|
* These tests verify that the error registry provides correct configurations
|
|
* for network and certificate errors.
|
|
*/
|
|
|
|
const REGISTRY_URL = "chrome://global/content/errors/error-registry.mjs";
|
|
const LOOKUP_URL = "chrome://global/content/errors/error-lookup.mjs";
|
|
const CERT_ERRORS_URL = "chrome://global/content/errors/cert-errors.mjs";
|
|
const PKIX_ERRORS_URL = "chrome://global/content/errors/pkix-errors.mjs";
|
|
const SSL_ERRORS_URL = "chrome://global/content/errors/ssl-errors.mjs";
|
|
const NET_ERRORS_URL = "chrome://global/content/errors/net-errors.mjs";
|
|
|
|
add_task(async function test_registry_exports() {
|
|
const registry = ChromeUtils.importESModule(REGISTRY_URL);
|
|
|
|
Assert.strictEqual(
|
|
typeof registry.getErrorConfig,
|
|
"function",
|
|
"getErrorConfig should be exported"
|
|
);
|
|
Assert.strictEqual(
|
|
typeof registry.registerError,
|
|
"function",
|
|
"registerError should be exported"
|
|
);
|
|
Assert.strictEqual(
|
|
typeof registry.isErrorSupported,
|
|
"function",
|
|
"isErrorSupported should be exported"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_lookup_exports() {
|
|
const lookup = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
Assert.strictEqual(
|
|
typeof lookup.errorHasNoUserFix,
|
|
"function",
|
|
"errorHasNoUserFix should be exported"
|
|
);
|
|
Assert.strictEqual(
|
|
typeof lookup.getResolvedErrorConfig,
|
|
"function",
|
|
"getResolvedErrorConfig should be exported"
|
|
);
|
|
Assert.strictEqual(
|
|
typeof lookup.isFeltPrivacySupported,
|
|
"function",
|
|
"isFeltPrivacySupported should be exported"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_unknown_error_returns_default() {
|
|
const { getErrorConfig } = ChromeUtils.importESModule(REGISTRY_URL);
|
|
|
|
const config = getErrorConfig("UNKNOWN_ERROR_12345");
|
|
|
|
Assert.strictEqual(
|
|
config,
|
|
undefined,
|
|
"Unknown error should return undefined"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_register_and_get_error() {
|
|
const { registerError, getErrorConfig, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
|
|
const testConfig = {
|
|
id: "TEST_ERROR_123",
|
|
errorCode: "TEST_ERROR_123",
|
|
category: "cert",
|
|
pageTitleL10nId: "test-page-title",
|
|
bodyTitleL10nId: "test-body-title",
|
|
buttons: {
|
|
showTryAgain: false,
|
|
showGoBack: true,
|
|
},
|
|
hasNoUserFix: true,
|
|
};
|
|
|
|
registerError(testConfig);
|
|
|
|
const retrieved = getErrorConfig("TEST_ERROR_123");
|
|
Assert.equal(retrieved.errorCode, "TEST_ERROR_123");
|
|
Assert.equal(retrieved.category, "cert");
|
|
Assert.equal(retrieved.pageTitleL10nId, "test-page-title");
|
|
Assert.equal(retrieved.hasNoUserFix, true);
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_is_error_supported() {
|
|
const { registerError, isErrorSupported, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
|
|
Assert.ok(
|
|
!isErrorSupported("TEST_ERROR_456"),
|
|
"Unregistered error should not be supported"
|
|
);
|
|
|
|
registerError({
|
|
id: "TEST_ERROR_456",
|
|
errorCode: "TEST_ERROR_456",
|
|
category: "net",
|
|
pageTitleL10nId: "test-title",
|
|
bodyTitleL10nId: "test-body",
|
|
buttons: {},
|
|
});
|
|
|
|
Assert.ok(
|
|
isErrorSupported("TEST_ERROR_456"),
|
|
"Registered error should be supported"
|
|
);
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_error_has_no_user_fix() {
|
|
const { registerError, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
const { errorHasNoUserFix } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
|
|
registerError({
|
|
id: "NO_FIX_ERROR",
|
|
errorCode: "NO_FIX_ERROR",
|
|
category: "cert",
|
|
pageTitleL10nId: "test-title",
|
|
bodyTitleL10nId: "test-body",
|
|
buttons: {},
|
|
hasNoUserFix: true,
|
|
});
|
|
|
|
registerError({
|
|
id: "HAS_FIX_ERROR",
|
|
errorCode: "HAS_FIX_ERROR",
|
|
category: "cert",
|
|
pageTitleL10nId: "test-title",
|
|
bodyTitleL10nId: "test-body",
|
|
buttons: {},
|
|
hasNoUserFix: false,
|
|
});
|
|
|
|
Assert.ok(
|
|
errorHasNoUserFix("NO_FIX_ERROR"),
|
|
"Error with hasNoUserFix=true should return true"
|
|
);
|
|
Assert.ok(
|
|
!errorHasNoUserFix("HAS_FIX_ERROR"),
|
|
"Error with hasNoUserFix=false should return false"
|
|
);
|
|
Assert.ok(
|
|
!errorHasNoUserFix("UNKNOWN_ERROR"),
|
|
"Unknown error should return false (default)"
|
|
);
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_resolve_l10n_args() {
|
|
const { resolveL10nArgs } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
const config = {
|
|
dataL10nId: "test-l10n-id",
|
|
dataL10nArgs: { hostname: null, otherArg: "static" },
|
|
};
|
|
|
|
const context = { hostname: "example.com" };
|
|
const resolved = resolveL10nArgs(config, context);
|
|
|
|
Assert.equal(resolved.dataL10nId, "test-l10n-id");
|
|
Assert.equal(resolved.dataL10nArgs.hostname, "example.com");
|
|
Assert.equal(resolved.dataL10nArgs.otherArg, "static");
|
|
});
|
|
|
|
add_task(async function test_resolve_l10n_args_null_input() {
|
|
const { resolveL10nArgs } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
const resolved = resolveL10nArgs(null, { hostname: "example.com" });
|
|
Assert.equal(resolved, null, "Null config should return null");
|
|
});
|
|
|
|
add_task(async function test_get_resolved_error_config() {
|
|
const { registerError, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
const { getResolvedErrorConfig } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
|
|
registerError({
|
|
id: "RESOLVE_TEST_ERROR",
|
|
errorCode: "RESOLVE_TEST_ERROR",
|
|
category: "cert",
|
|
pageTitleL10nId: "test-title",
|
|
bodyTitleL10nId: "test-body",
|
|
introContent: {
|
|
dataL10nId: "test-intro",
|
|
dataL10nArgs: { hostname: null },
|
|
},
|
|
shortDescription: {
|
|
dataL10nId: "test-short-desc",
|
|
dataL10nArgs: { hostname: null },
|
|
},
|
|
buttons: {},
|
|
hasNoUserFix: false,
|
|
});
|
|
|
|
const context = { hostname: "test.example.com" };
|
|
const resolved = getResolvedErrorConfig("RESOLVE_TEST_ERROR", context);
|
|
|
|
Assert.equal(resolved.errorCode, "RESOLVE_TEST_ERROR");
|
|
Assert.equal(resolved.introContent.dataL10nArgs.hostname, "test.example.com");
|
|
Assert.equal(
|
|
resolved.shortDescription.dataL10nArgs.hostname,
|
|
"test.example.com"
|
|
);
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_get_errors_by_category() {
|
|
const { registerErrors, getErrorsByCategory, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
|
|
registerErrors([
|
|
{
|
|
id: "CERT_ERROR_1",
|
|
errorCode: "CERT_ERROR_1",
|
|
category: "cert",
|
|
pageTitleL10nId: "t1",
|
|
bodyTitleL10nId: "b1",
|
|
buttons: {},
|
|
},
|
|
{
|
|
id: "CERT_ERROR_2",
|
|
errorCode: "CERT_ERROR_2",
|
|
category: "cert",
|
|
pageTitleL10nId: "t2",
|
|
bodyTitleL10nId: "b2",
|
|
buttons: {},
|
|
},
|
|
{
|
|
id: "NET_ERROR_1",
|
|
errorCode: "NET_ERROR_1",
|
|
category: "net",
|
|
pageTitleL10nId: "t3",
|
|
bodyTitleL10nId: "b3",
|
|
buttons: {},
|
|
},
|
|
]);
|
|
|
|
const certErrors = getErrorsByCategory("cert");
|
|
const netErrors = getErrorsByCategory("net");
|
|
|
|
Assert.equal(certErrors.length, 2, "Should have 2 cert errors");
|
|
Assert.equal(netErrors.length, 1, "Should have 1 net error");
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_is_felt_privacy_supported() {
|
|
const { registerError, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
const { isFeltPrivacySupported } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
|
|
registerError({
|
|
id: "FP_SUPPORTED_ERROR",
|
|
errorCode: "FP_SUPPORTED_ERROR",
|
|
category: "cert",
|
|
pageTitleL10nId: "test-title",
|
|
bodyTitleL10nId: "test-body",
|
|
introContent: { id: "fp-intro" },
|
|
buttons: {},
|
|
});
|
|
|
|
registerError({
|
|
id: "fp-another-supported-error",
|
|
category: "net",
|
|
pageTitleL10nId: "test-title",
|
|
bodyTitleL10nId: "test-body",
|
|
buttons: {},
|
|
});
|
|
|
|
Assert.ok(
|
|
isFeltPrivacySupported("FP_SUPPORTED_ERROR"),
|
|
"Registered error should support Felt Privacy"
|
|
);
|
|
Assert.ok(
|
|
isFeltPrivacySupported("fp-another-supported-error"),
|
|
"All registered errors should support Felt Privacy"
|
|
);
|
|
Assert.ok(
|
|
!isFeltPrivacySupported("NONEXISTENT_ERROR"),
|
|
"Unregistered error should not support Felt Privacy"
|
|
);
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_register_error_throws_without_id() {
|
|
const { registerError } = ChromeUtils.importESModule(REGISTRY_URL);
|
|
|
|
Assert.throws(
|
|
() => registerError({}),
|
|
/Error configuration must have an id/,
|
|
"registerError should throw when config has no id"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_registered_config_is_frozen() {
|
|
const { registerError, getErrorConfig, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
|
|
registerError({
|
|
id: "FROZEN_TEST_ERROR",
|
|
errorCode: "FROZEN_TEST_ERROR",
|
|
category: "cert",
|
|
pageTitleL10nId: "test-title",
|
|
bodyTitleL10nId: "test-body",
|
|
buttons: {},
|
|
});
|
|
|
|
const config = getErrorConfig("FROZEN_TEST_ERROR");
|
|
Assert.ok(Object.isFrozen(config), "Registered config should be frozen");
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_duplicate_registration_throws() {
|
|
const { registerError, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
|
|
registerError({
|
|
id: "DUP_TEST_ERROR",
|
|
errorCode: "DUP_TEST_ERROR",
|
|
category: "cert",
|
|
pageTitleL10nId: "test-title",
|
|
bodyTitleL10nId: "test-body",
|
|
buttons: {},
|
|
});
|
|
|
|
Assert.throws(
|
|
() =>
|
|
registerError({
|
|
id: "DUP_TEST_ERROR",
|
|
errorCode: "DUP_TEST_ERROR",
|
|
category: "net",
|
|
pageTitleL10nId: "test-title-2",
|
|
bodyTitleL10nId: "test-body-2",
|
|
buttons: {},
|
|
}),
|
|
/Duplicate error registration/,
|
|
"registerError should throw when a duplicate id is registered"
|
|
);
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_initialize_registry_count() {
|
|
const { initializeRegistry, getErrorCount, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
const { CERT_ERRORS } = ChromeUtils.importESModule(CERT_ERRORS_URL);
|
|
const { PKIX_ERRORS } = ChromeUtils.importESModule(PKIX_ERRORS_URL);
|
|
const { SSL_ERRORS } = ChromeUtils.importESModule(SSL_ERRORS_URL);
|
|
const { NET_ERRORS } = ChromeUtils.importESModule(NET_ERRORS_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
initializeRegistry();
|
|
|
|
const expectedCount =
|
|
CERT_ERRORS.length +
|
|
PKIX_ERRORS.length +
|
|
SSL_ERRORS.length +
|
|
NET_ERRORS.length;
|
|
Assert.equal(
|
|
getErrorCount(),
|
|
expectedCount,
|
|
"initializeRegistry should register all errors from all sources"
|
|
);
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_resolve_l10n_args_resolution() {
|
|
const { resolveL10nArgs } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
const config = {
|
|
dataL10nId: "x",
|
|
dataL10nArgs: { hostname: "" },
|
|
};
|
|
const resolved = resolveL10nArgs(config, { hostname: "example.com" });
|
|
Assert.equal(
|
|
resolved.dataL10nArgs.hostname,
|
|
"example.com",
|
|
"Empty string should be replaced with runtime value"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_dataL10nId_configured_as_function() {
|
|
const { resolveL10nArgs } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
const fn = ctx => (ctx.cssClass === "badStsCert" ? "sts-id" : "normal-id");
|
|
const config1 = { dataL10nId: fn, dataL10nArgs: {} };
|
|
const config2 = { dataL10nId: fn, dataL10nArgs: {} };
|
|
|
|
const resolved1 = resolveL10nArgs(config1, { cssClass: "badStsCert" });
|
|
Assert.equal(
|
|
resolved1.dataL10nId,
|
|
"sts-id",
|
|
"Function dataL10nId should resolve with badStsCert context"
|
|
);
|
|
|
|
const resolved2 = resolveL10nArgs(config2, { cssClass: "other" });
|
|
Assert.equal(
|
|
resolved2.dataL10nId,
|
|
"normal-id",
|
|
"Function dataL10nId should resolve with non-badStsCert context"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_dataL10nArgs_param_as_function() {
|
|
const { resolveL10nArgs } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
const config = {
|
|
dataL10nId: "x",
|
|
dataL10nArgs: { date: ctx => ctx.errorInfo.validNotAfter },
|
|
};
|
|
const resolved = resolveL10nArgs(config, {
|
|
errorInfo: { validNotAfter: 12345 },
|
|
});
|
|
Assert.equal(
|
|
resolved.dataL10nArgs.date,
|
|
12345,
|
|
"Configured function in l10n args should be replaced with its return value"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_resolve_many_l10n_args() {
|
|
const { resolveManyL10nArgs } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
const configs = [
|
|
{ dataL10nId: "a", dataL10nArgs: { hostname: null } },
|
|
{ dataL10nId: "b", dataL10nArgs: { hostname: null } },
|
|
];
|
|
const resolved = resolveManyL10nArgs(configs, { hostname: "example.com" });
|
|
Assert.equal(
|
|
resolved[0].dataL10nArgs.hostname,
|
|
"example.com",
|
|
"First config hostname should be resolved"
|
|
);
|
|
Assert.equal(
|
|
resolved[1].dataL10nArgs.hostname,
|
|
"example.com",
|
|
"Second config hostname should be resolved"
|
|
);
|
|
|
|
const nullResult = resolveManyL10nArgs(null, { hostname: "example.com" });
|
|
Assert.strictEqual(nullResult, null, "Null input should return null");
|
|
});
|
|
|
|
add_task(async function test_resolve_description_parts_static_array() {
|
|
const { resolveDescriptionParts } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
const parts = [
|
|
{ dataL10nId: "part-one", dataL10nArgs: { hostname: null } },
|
|
{ dataL10nId: "part-two", dataL10nArgs: { hostname: null } },
|
|
];
|
|
const resolved = resolveDescriptionParts(parts, { hostname: "example.com" });
|
|
Assert.equal(
|
|
resolved[0].dataL10nArgs.hostname,
|
|
"example.com",
|
|
"First description part hostname should be resolved"
|
|
);
|
|
Assert.equal(
|
|
resolved[1].dataL10nArgs.hostname,
|
|
"example.com",
|
|
"Second description part hostname should be resolved"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_resolve_description_parts_function_online() {
|
|
const { resolveDescriptionParts } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
const { DESCRIPTION_PARTS_MAP } = ChromeUtils.importESModule(NET_ERRORS_URL);
|
|
|
|
const result = resolveDescriptionParts(
|
|
DESCRIPTION_PARTS_MAP.dnsNotFoundDescription,
|
|
{ noConnectivity: false }
|
|
);
|
|
Assert.ok(
|
|
result.some(p => p.dataL10nId === "neterror-dns-not-found-hint-header"),
|
|
"Online branch should include neterror-dns-not-found-hint-header"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_resolve_description_parts_function_offline() {
|
|
const { resolveDescriptionParts } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
const { DESCRIPTION_PARTS_MAP } = ChromeUtils.importESModule(NET_ERRORS_URL);
|
|
|
|
const result = resolveDescriptionParts(
|
|
DESCRIPTION_PARTS_MAP.dnsNotFoundDescription,
|
|
{ noConnectivity: true }
|
|
);
|
|
Assert.ok(
|
|
result.some(
|
|
p => p.dataL10nId === "neterror-dns-not-found-offline-hint-header"
|
|
),
|
|
"Offline branch should include neterror-dns-not-found-offline-hint-header"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_resolve_description_parts_null() {
|
|
const { resolveDescriptionParts } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
const result = resolveDescriptionParts(null, {});
|
|
Assert.deepEqual(
|
|
result,
|
|
[],
|
|
"Null descriptionParts should return empty array"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_resolve_advanced_config() {
|
|
const { registerError, getErrorConfig, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
const { resolveAdvancedConfig } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
|
|
registerError({
|
|
id: "ADV_TEST_ERROR",
|
|
errorCode: "ADV_TEST_ERROR",
|
|
category: "cert",
|
|
pageTitleL10nId: "test-title",
|
|
bodyTitleL10nId: "test-body",
|
|
buttons: {},
|
|
advanced: {
|
|
whyDangerous: { dataL10nId: "x", dataL10nArgs: { hostname: null } },
|
|
whatCanYouDo: { dataL10nId: "y", dataL10nArgs: { hostname: null } },
|
|
learnMore: { dataL10nId: "z", dataL10nArgs: { hostname: null } },
|
|
},
|
|
});
|
|
|
|
const config = getErrorConfig("ADV_TEST_ERROR");
|
|
const resolved = resolveAdvancedConfig(config.advanced, {
|
|
hostname: "example.com",
|
|
});
|
|
|
|
Assert.equal(
|
|
resolved.whyDangerous.dataL10nArgs.hostname,
|
|
"example.com",
|
|
"whyDangerous hostname should be resolved"
|
|
);
|
|
Assert.equal(
|
|
resolved.whatCanYouDo.dataL10nArgs.hostname,
|
|
"example.com",
|
|
"whatCanYouDo hostname should be resolved"
|
|
);
|
|
Assert.equal(
|
|
resolved.learnMore.dataL10nArgs.hostname,
|
|
"example.com",
|
|
"learnMore hostname should be resolved"
|
|
);
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_resolve_advanced_config_null() {
|
|
const { resolveAdvancedConfig } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
const result = resolveAdvancedConfig(null, {});
|
|
Assert.strictEqual(result, null, "Null advancedConfig should return null");
|
|
});
|
|
|
|
add_task(async function test_ssl_error_rx_record_too_long_registered() {
|
|
const { initializeRegistry, getErrorConfig, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
initializeRegistry();
|
|
|
|
const config = getErrorConfig("SSL_ERROR_RX_RECORD_TOO_LONG");
|
|
Assert.ok(config, "SSL_ERROR_RX_RECORD_TOO_LONG should be registered");
|
|
Assert.equal(config.category, "cert", "Should be in the cert category");
|
|
Assert.equal(
|
|
config.bodyTitleL10nId,
|
|
"nssFailure2-title",
|
|
"Should have the nssFailure2 title for consistency with other SSL errors"
|
|
);
|
|
Assert.ok(
|
|
Array.isArray(config.introContent),
|
|
"introContent should be an array"
|
|
);
|
|
Assert.equal(
|
|
config.introContent[0].dataL10nId,
|
|
"cert-error-ssl-connection-error",
|
|
"First intro content should be the SSL connection error message"
|
|
);
|
|
Assert.equal(
|
|
config.introContent[1].dataL10nId,
|
|
"ssl-error-rx-record-too-long",
|
|
"Second intro content should be the specific error message"
|
|
);
|
|
Assert.ok(config.buttons.showTryAgain, "Should show try again button");
|
|
Assert.ok(config.buttons.showAdvanced, "Should show advanced section");
|
|
Assert.equal(config.hasNoUserFix, true, "Should have no user fix");
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_denied_port_access_intro_content() {
|
|
const { initializeRegistry, getErrorConfig, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
initializeRegistry();
|
|
|
|
const config = getErrorConfig("deniedPortAccess");
|
|
Assert.ok(config, "deniedPortAccess should be registered");
|
|
Assert.equal(
|
|
config.introContent.dataL10nId,
|
|
"fp-neterror-denied-port-access",
|
|
"Should use the denied port access l10n id, not the offline intro"
|
|
);
|
|
Assert.strictEqual(
|
|
config.introContent.dataL10nArgs,
|
|
undefined,
|
|
"Should not have l10n args (no hostname needed)"
|
|
);
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_clock_skew_errors_have_checkClockSkew() {
|
|
const { initializeRegistry, getErrorConfig, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
initializeRegistry();
|
|
|
|
const clockSkewErrorIds = [
|
|
"SEC_ERROR_EXPIRED_CERTIFICATE",
|
|
"SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE",
|
|
"MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE",
|
|
"MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE",
|
|
];
|
|
|
|
for (const id of clockSkewErrorIds) {
|
|
const config = getErrorConfig(id);
|
|
Assert.ok(config, `${id} should be registered`);
|
|
Assert.equal(
|
|
config.checkClockSkew,
|
|
true,
|
|
`${id} should have checkClockSkew: true`
|
|
);
|
|
}
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_resolve_error_id_nss_fallthrough() {
|
|
const { registerError, isErrorSupported, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
const { resolveErrorID } = ChromeUtils.importESModule(LOOKUP_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
|
|
registerError({
|
|
id: "nssFailure2",
|
|
errorCode: "nssFailure2",
|
|
category: "cert",
|
|
pageTitleL10nId: "test-title",
|
|
bodyTitleL10nId: "test-body",
|
|
buttons: {},
|
|
});
|
|
|
|
Assert.ok(
|
|
isErrorSupported("nssFailure2"),
|
|
"nssFailure2 should be registered"
|
|
);
|
|
|
|
Assert.strictEqual(
|
|
resolveErrorID({
|
|
errorCodeString: "SSL_ERROR_RX_CERTIFICATE_REQUIRED_ALERT",
|
|
gErrorCode: "nssFailure2",
|
|
noConnectivity: false,
|
|
vpnActive: false,
|
|
}),
|
|
"nssFailure2",
|
|
"Unrecognized errorCodeString with gErrorCode=nssFailure2 should fall through to nssFailure2"
|
|
);
|
|
|
|
Assert.strictEqual(
|
|
resolveErrorID({
|
|
errorCodeString: "SSL_ERROR_RX_CERTIFICATE_REQUIRED_ALERT",
|
|
gErrorCode: "dnsNotFound",
|
|
noConnectivity: false,
|
|
vpnActive: false,
|
|
}),
|
|
null,
|
|
"Unrecognized errorCodeString with gErrorCode other than nssFailure2 should return null"
|
|
);
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_dns_not_found_what_can_you_do_items() {
|
|
const { initializeRegistry, getErrorConfig, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
initializeRegistry();
|
|
|
|
const config = getErrorConfig("dnsNotFound");
|
|
Assert.ok(config, "dnsNotFound should be registered");
|
|
|
|
const items = config.customNetError?.whatCanYouDoItems;
|
|
Assert.ok(
|
|
Array.isArray(items),
|
|
"dnsNotFound customNetError should have a whatCanYouDoItems array"
|
|
);
|
|
Assert.equal(items.length, 3, "whatCanYouDoItems should have 3 entries");
|
|
Assert.ok(
|
|
items.includes("neterror-http-empty-response"),
|
|
"whatCanYouDoItems should include neterror-http-empty-response"
|
|
);
|
|
Assert.ok(
|
|
items.includes("neterror-dns-not-found-hint-check-network-2"),
|
|
"whatCanYouDoItems should include neterror-dns-not-found-hint-check-network-2"
|
|
);
|
|
Assert.ok(
|
|
items.includes("neterror-dns-not-found-hint-firewall-2"),
|
|
"whatCanYouDoItems should include neterror-dns-not-found-hint-firewall-2"
|
|
);
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|
|
|
|
add_task(async function test_sec_error_ca_cert_invalid_registered() {
|
|
const { initializeRegistry, getErrorConfig, _testOnlyClearRegistry } =
|
|
ChromeUtils.importESModule(REGISTRY_URL);
|
|
|
|
_testOnlyClearRegistry();
|
|
initializeRegistry();
|
|
|
|
const config = getErrorConfig("SEC_ERROR_CA_CERT_INVALID");
|
|
Assert.ok(config, "SEC_ERROR_CA_CERT_INVALID should be registered");
|
|
Assert.equal(config.category, "cert", "Should be in the cert category");
|
|
Assert.ok(
|
|
config.buttons.showAddException,
|
|
"Should show the exception button"
|
|
);
|
|
Assert.ok(config.buttons.showAdvanced, "Should show the advanced section");
|
|
Assert.equal(config.hasNoUserFix, true, "Should have no user fix");
|
|
Assert.equal(
|
|
config.advanced.whyDangerous.dataL10nId,
|
|
"fp-certerror-invalid-cert-why-dangerous",
|
|
"Should use the invalid cert why-dangerous l10n id"
|
|
);
|
|
Assert.equal(
|
|
config.advanced.whatCanYouDo.dataL10nId,
|
|
"fp-certerror-untrusted-issuer-what-can-you-do-body",
|
|
"Should reuse the untrusted issuer what-can-you-do l10n id"
|
|
);
|
|
|
|
_testOnlyClearRegistry();
|
|
});
|