commit 0c1efe49759aff467d31238ea10851c30bf83315
parent 3352c88229b2c228aa6421bddd3f97f1fa8f3fe0
Author: smayya <smayya@mozilla.com>
Date: Wed, 15 Oct 2025 12:16:28 +0000
Bug 1988152 - support configuration to skip LNA checks target domains. r=necko-reviewers,valentin
Support suffix wildcard matching and exact domain matching configuration through the pref.
Differential Revision: https://phabricator.services.mozilla.com/D266982
Diffstat:
7 files changed, 463 insertions(+), 0 deletions(-)
diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml
@@ -14493,6 +14493,13 @@
value: true
mirror: always
+# Comma-separated list of domains to skip LNA checks for.
+# Supports suffix wildcard patterns (*.example.com)
+- name: network.lna.skip-domains
+ type: String
+ value: ""
+ mirror: never
+
# The proxy type. See nsIProtocolProxyService.idl
# PROXYCONFIG_DIRECT = 0
# PROXYCONFIG_MANUAL = 1
diff --git a/netwerk/base/LNAPermissionRequest.cpp b/netwerk/base/LNAPermissionRequest.cpp
@@ -13,6 +13,8 @@
#include "mozilla/glean/NetwerkMetrics.h"
#include "mozilla/dom/WindowGlobalParent.h"
+#include "nsIIOService.h"
+#include "nsIOService.h"
namespace mozilla::net {
@@ -107,6 +109,18 @@ nsresult LNAPermissionRequest::RequestPermission() {
return Cancel();
}
+ // Check if the domain should skip LNA checks
+ if (mPrincipal && gIOService) {
+ nsAutoCString origin;
+ nsresult rv = mPrincipal->GetAsciiHost(origin);
+ if (NS_SUCCEEDED(rv) && !origin.IsEmpty()) {
+ if (gIOService->ShouldSkipDomainForLNA(origin)) {
+ // Domain is in the skip list, grant permission automatically
+ return Allow(JS::UndefinedHandleValue);
+ }
+ }
+ }
+
PromptResult pr = CheckPromptPrefs();
if (pr == PromptResult::Granted) {
return Allow(JS::UndefinedHandleValue);
diff --git a/netwerk/base/nsIOService.cpp b/netwerk/base/nsIOService.cpp
@@ -105,6 +105,7 @@ using mozilla::dom::ServiceWorkerDescriptor;
#define PREF_LNA_IP_ADDR_SPACE_PRIVATE \
"network.lna.address_space.private.override"
#define PREF_LNA_IP_ADDR_SPACE_LOCAL "network.lna.address_space.local.override"
+#define PREF_LNA_SKIP_DOMAINS "network.lna.skip-domains"
nsIOService* gIOService;
static bool gCaptivePortalEnabled = false;
@@ -234,6 +235,7 @@ static const char* gCallbackPrefs[] = {
PREF_LNA_IP_ADDR_SPACE_PUBLIC,
PREF_LNA_IP_ADDR_SPACE_PRIVATE,
PREF_LNA_IP_ADDR_SPACE_LOCAL,
+ PREF_LNA_SKIP_DOMAINS,
nullptr,
};
@@ -1662,6 +1664,10 @@ void nsIOService::PrefsChanged(const char* pref) {
UpdateAddressSpaceOverrideList(PREF_LNA_IP_ADDR_SPACE_LOCAL,
mLocalAddressSpaceOverrideList);
}
+ if (!pref || strncmp(pref, PREF_LNA_SKIP_DOMAINS,
+ strlen(PREF_LNA_SKIP_DOMAINS)) == 0) {
+ UpdateSkipDomainsList();
+ }
}
void nsIOService::UpdateAddressSpaceOverrideList(
@@ -1680,6 +1686,52 @@ void nsIOService::UpdateAddressSpaceOverrideList(
aTargetList = std::move(addressSpaceOverridesArray);
}
+void nsIOService::UpdateSkipDomainsList() {
+ nsAutoCString skipDomains;
+ Preferences::GetCString(PREF_LNA_SKIP_DOMAINS, skipDomains);
+
+ nsTArray<nsCString> skipDomainsArray;
+ nsCCharSeparatedTokenizer tokenizer(skipDomains, ',');
+ while (tokenizer.hasMoreTokens()) {
+ nsAutoCString token(tokenizer.nextToken());
+ token.StripWhitespace();
+ if (!token.IsEmpty()) {
+ skipDomainsArray.AppendElement(token);
+ }
+ }
+
+ AutoWriteLock lock(mLock);
+ mLNASkipDomainsList = std::move(skipDomainsArray);
+}
+
+bool nsIOService::ShouldSkipDomainForLNA(const nsACString& aDomain) {
+ AutoReadLock lock(mLock);
+
+ // Check each domain pattern
+ for (const auto& pattern : mLNASkipDomainsList) {
+ // Special case: plain "*" matches all domains
+ if (pattern.Equals("*"_ns)) {
+ return true;
+ }
+
+ // Suffix wildcard pattern (starts with *.)
+ if (StringBeginsWith(pattern, "*."_ns)) {
+ nsDependentCSubstring suffix(Substring(pattern, 2));
+ nsDependentCSubstring suffixWithDot(Substring(pattern, 1));
+ if (aDomain == suffix || StringEndsWith(aDomain, suffixWithDot)) {
+ return true;
+ }
+ }
+
+ // Exact match
+ if (pattern == aDomain) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void nsIOService::ParsePortList(const char* pref, bool remove) {
nsAutoCString portList;
nsTArray<int32_t> restrictedPortList;
diff --git a/netwerk/base/nsIOService.h b/netwerk/base/nsIOService.h
@@ -158,6 +158,8 @@ class nsIOService final : public nsIIOService,
NS_IMETHODIMP GetOverridenIpAddressSpace(
nsILoadInfo::IPAddressSpace* aIpAddressSpace, const NetAddr& aAddr);
+ bool ShouldSkipDomainForLNA(const nsACString& aDomain);
+
private:
// These shouldn't be called directly:
// - construct using GetInstance
@@ -213,6 +215,7 @@ class nsIOService final : public nsIIOService,
void UpdateAddressSpaceOverrideList(const char* aPrefName,
nsTArray<nsCString>& aTargetList);
+ void UpdateSkipDomainsList();
private:
mozilla::Atomic<bool, mozilla::Relaxed> mOffline{true};
@@ -247,6 +250,7 @@ class nsIOService final : public nsIIOService,
nsTArray<nsCString> mPublicAddressSpaceOverridesList MOZ_GUARDED_BY(mLock);
nsTArray<nsCString> mPrivateAddressSpaceOverridesList MOZ_GUARDED_BY(mLock);
nsTArray<nsCString> mLocalAddressSpaceOverrideList MOZ_GUARDED_BY(mLock);
+ nsTArray<nsCString> mLNASkipDomainsList MOZ_GUARDED_BY(mLock);
nsTHashMap<nsCString, RuntimeProtocolHandler> mRuntimeProtocolHandlers
MOZ_GUARDED_BY(mLock);
diff --git a/netwerk/protocol/http/nsHttpTransaction.cpp b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -63,6 +63,7 @@
#include "nsTransportUtils.h"
#include "sslerr.h"
#include "SpeculativeTransaction.h"
+#include "mozilla/Preferences.h"
//-----------------------------------------------------------------------------
@@ -3737,10 +3738,17 @@ nsILoadInfo::IPAddressSpace nsHttpTransaction::GetTargetIPAddressSpace() {
bool nsHttpTransaction::AllowedToConnectToIpAddressSpace(
nsILoadInfo::IPAddressSpace aTargetIpAddressSpace) {
// skip checks if LNA feature is disabled
+
if (!StaticPrefs::network_lna_enabled()) {
return true;
}
+ // Skip LNA checks if domain is in skip list
+ if (mConnInfo && gIOService &&
+ gIOService->ShouldSkipDomainForLNA(mConnInfo->GetOrigin())) {
+ return true;
+ }
+
// store targetIpAddress space which is required later by nsHttpChannel for
// permission prompts
{
diff --git a/netwerk/test/gtest/TestLocalNetworkAccess.cpp b/netwerk/test/gtest/TestLocalNetworkAccess.cpp
@@ -8,6 +8,8 @@
#include "mozilla/StaticPrefs_network.h"
#include "mozilla/Preferences.h"
#include "mozilla/net/DNS.h"
+#include "nsNetUtil.h"
+#include "nsIOService.h"
TEST(TestNetAddrLNAUtil, IPAddressSpaceCategorization)
{
@@ -150,3 +152,115 @@ TEST(TestNetAddrLNAUtil, DefaultAndOverrideTransitions)
<< "Expected reset back to default space for " << tc.ip;
}
}
+
+TEST(TestNetAddrLNAUtil, ShouldSkipDomainForLNA)
+{
+ using mozilla::Preferences;
+
+ // Get nsIOService instance
+ nsIOService* ioService = gIOService;
+ ASSERT_NE(ioService, nullptr);
+
+ // Test with empty preference (should not skip any domains)
+ Preferences::SetCString("network.lna.skip-domains", ""_ns);
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("example.com"_ns));
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("test.example.com"_ns));
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("localhost"_ns));
+
+ // Test exact domain matching
+ Preferences::SetCString("network.lna.skip-domains",
+ "example.com,test.org"_ns);
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("example.com"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("test.org"_ns));
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("sub.example.com"_ns));
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("example.org"_ns));
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("notexample.com"_ns));
+
+ // Test wildcard domain matching
+ Preferences::SetCString("network.lna.skip-domains",
+ "*.example.com,*.test.org"_ns);
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("sub.example.com"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("deep.sub.example.com"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("api.test.org"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA(
+ "example.com"_ns)); // Should match exact domain too
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA(
+ "test.org"_ns)); // Should match exact domain too
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("example.net"_ns));
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("notexample.com"_ns));
+
+ // Test more suffix wildcard patterns
+ Preferences::SetCString("network.lna.skip-domains",
+ "*.local,*.internal,*.test"_ns);
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("server.local"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("api.internal"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("service.test"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("deep.subdomain.local"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA(
+ "local"_ns)); // Should match exact domain too
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA(
+ "internal"_ns)); // Should match exact domain too
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("local.example.com"_ns));
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("localhost"_ns));
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("example.com"_ns));
+
+ // Test mixed patterns (exact and suffix wildcard)
+ Preferences::SetCString(
+ "network.lna.skip-domains",
+ "localhost,*.dev.local,*.staging.com,production.example.com"_ns);
+ // Exact matches
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("localhost"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("production.example.com"_ns));
+ // Suffix wildcard matches
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("api.dev.local"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("web.dev.local"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("dev.local"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("test.staging.com"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("api.staging.com"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("staging.com"_ns));
+ // Non-matches
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("example.com"_ns));
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("dev.example.com"_ns));
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("staging.example.com"_ns));
+
+ // Test with whitespace and empty entries
+ Preferences::SetCString(
+ "network.lna.skip-domains",
+ " example.com , , *.test.local , admin.internal "_ns);
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("example.com"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("api.test.local"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("admin.internal"_ns));
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("test.com"_ns));
+
+ // Test invalid patterns (unknown patterns treated as exact match)
+ Preferences::SetCString("network.lna.skip-domains",
+ "example.com,invalid.pattern"_ns);
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA(
+ "example.com"_ns)); // Valid exact match
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA(
+ "invalid.pattern"_ns)); // Treated as exact match
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA("test.com"_ns)); // No match
+
+ // Test case sensitivity
+ Preferences::SetCString("network.lna.skip-domains",
+ "Example.COM,*.Test.ORG"_ns);
+ EXPECT_TRUE(
+ ioService->ShouldSkipDomainForLNA("Example.COM"_ns)); // Exact case match
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA(
+ "example.com"_ns)); // Different case (no match)
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA(
+ "api.Test.ORG"_ns)); // Wildcard case match
+ EXPECT_FALSE(ioService->ShouldSkipDomainForLNA(
+ "api.test.org"_ns)); // Different case (no match)
+
+ // Test plain "*" matches all domains
+ Preferences::SetCString("network.lna.skip-domains", "*"_ns);
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("example.com"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("test.org"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("localhost"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("any.domain.here"_ns));
+ EXPECT_TRUE(ioService->ShouldSkipDomainForLNA("server.local"_ns));
+
+ // Reset preference for cleanup
+ Preferences::SetCString("network.lna.skip-domains", ""_ns);
+}
diff --git a/netwerk/test/unit/test_local_network_access.js b/netwerk/test/unit/test_local_network_access.js
@@ -7,6 +7,10 @@ const { NodeHTTP2Server } = ChromeUtils.importESModule(
"resource://testing-common/NodeServer.sys.mjs"
);
+const override = Cc["@mozilla.org/network/native-dns-override;1"].getService(
+ Ci.nsINativeDNSResolverOverride
+);
+
function makeChannel(url) {
let uri2 = NetUtil.newURI(url);
// by default system principal is used, which cannot be used for permission based tests
@@ -50,6 +54,22 @@ ChromeUtils.defineLazyGetter(this, "H2_URL", function () {
return "https://localhost:" + server.port();
});
+ChromeUtils.defineLazyGetter(this, "H1_EXAMPLE_URL", function () {
+ return "http://example.com:" + httpServer.identity.primaryPort;
+});
+
+ChromeUtils.defineLazyGetter(this, "H1_TEST_EXAMPLE_URL", function () {
+ return "http://test.example.com:" + httpServer.identity.primaryPort;
+});
+
+ChromeUtils.defineLazyGetter(this, "H1_SERVER_LOCAL_URL", function () {
+ return "http://server.local:" + httpServer.identity.primaryPort;
+});
+
+ChromeUtils.defineLazyGetter(this, "H1_API_DEV_LOCAL_URL", function () {
+ return "http://api.dev.local:" + httpServer.identity.primaryPort;
+});
+
let httpServer = null;
let server = new NodeHTTP2Server();
function pathHandler(metadata, response) {
@@ -73,6 +93,11 @@ add_setup(async () => {
httpServer = new HttpServer();
httpServer.registerPathHandler("/test_lna", pathHandler);
httpServer.start(-1);
+ // Add domain identities for testing domain skip patterns
+ httpServer.identity.add("http", "example.com", 80);
+ httpServer.identity.add("http", "test.example.com", 80);
+ httpServer.identity.add("http", "server.local", 80);
+ httpServer.identity.add("http", "api.dev.local", 80);
// H2 Server
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
@@ -310,3 +335,242 @@ add_task(async function lna_blocking_tests_local_network() {
}
}
});
+
+// Test the network.lna.skip-domains preference
+add_task(async function lna_domain_skip_tests() {
+ // Add DNS overrides to map test domains to 127.0.0.1
+ override.clearOverrides();
+ Services.dns.clearCache(true);
+
+ override.addIPOverride("example.com", "127.0.0.1");
+ override.addIPOverride("test.example.com", "127.0.0.1");
+ override.addIPOverride("server.local", "127.0.0.1");
+ override.addIPOverride("api.dev.local", "127.0.0.1");
+
+ // Add override such that target servers are considered as local network (and not localhost)
+ // This includes all the domains we're testing with
+ var override_value =
+ "127.0.0.1" +
+ ":" +
+ httpServer.identity.primaryPort +
+ "," +
+ "127.0.0.1" +
+ ":" +
+ server.port();
+
+ Services.prefs.setCharPref(
+ "network.lna.address_space.private.override",
+ override_value
+ );
+
+ const domainSkipTestCases = [
+ // [skipDomains, parentSpace, expectedStatus, baseURL, description]
+ // Exact domain match
+ [
+ "localhost",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_URL,
+ "exact domain match - localhost",
+ ],
+ [
+ "localhost",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H2_URL,
+ "exact domain match - localhost H2",
+ ],
+ [
+ "example.com",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_EXAMPLE_URL,
+ "exact domain match - example.com",
+ ],
+
+ // Wildcard domain match
+ [
+ "*.localhost",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_URL,
+ "wildcard domain match - *.localhost matches localhost",
+ ],
+ [
+ "*.example.com",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_TEST_EXAMPLE_URL,
+ "wildcard domain match - *.example.com matches test.example.com",
+ ],
+ [
+ "*.example.com",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_EXAMPLE_URL,
+ "wildcard domain match - *.example.com matches example.com",
+ ],
+ [
+ "*.test.com",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED,
+ H1_EXAMPLE_URL,
+ "wildcard no match - *.test.com doesn't match example.com",
+ ],
+
+ // Multiple domains (comma-separated)
+ [
+ "example.com,localhost,test.org",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_URL,
+ "multiple domains - localhost match",
+ ],
+ [
+ "example.com,localhost,test.org",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_EXAMPLE_URL,
+ "multiple domains - example.com match",
+ ],
+ [
+ "foo.com,test.org",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED,
+ H1_EXAMPLE_URL,
+ "multiple domains no match - example.com not in list",
+ ],
+
+ // Empty skip domains (should apply normal LNA rules)
+ [
+ "",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED,
+ H1_URL,
+ "empty skip domains - should block",
+ ],
+
+ // .local domain tests
+ [
+ "*.local",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_SERVER_LOCAL_URL,
+ "wildcard .local - *.local matches server.local",
+ ],
+ [
+ "*.local",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_API_DEV_LOCAL_URL,
+ "wildcard .local - *.local matches api.dev.local",
+ ],
+ [
+ "*.dev.local",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_API_DEV_LOCAL_URL,
+ "wildcard subdomain .local - *.dev.local matches api.dev.local",
+ ],
+ [
+ "server.local",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_SERVER_LOCAL_URL,
+ "exact match .local - server.local matches server.local",
+ ],
+ [
+ "*.local",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED,
+ H1_URL,
+ "wildcard .local - *.local doesn't match localhost",
+ ],
+
+ // localhost variations
+ [
+ "localhost,*.local,*.internal",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_URL,
+ "combined patterns - localhost matches localhost",
+ ],
+ [
+ "localhost,*.local,*.internal",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_SERVER_LOCAL_URL,
+ "combined patterns - *.local matches server.local",
+ ],
+
+ // Plain "*" wildcard matches all domains
+ [
+ "*",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_URL,
+ "wildcard all - * matches localhost",
+ ],
+ [
+ "*",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_EXAMPLE_URL,
+ "wildcard all - * matches example.com",
+ ],
+ [
+ "*",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_SERVER_LOCAL_URL,
+ "wildcard all - * matches server.local",
+ ],
+ [
+ "*",
+ Ci.nsILoadInfo.Public,
+ Cr.NS_OK,
+ H1_TEST_EXAMPLE_URL,
+ "wildcard all - * matches test.example.com",
+ ],
+ ];
+
+ for (let [
+ skipDomains,
+ parentSpace,
+ expectedStatus,
+ url,
+ description,
+ ] of domainSkipTestCases) {
+ info(`Testing domain skip: ${description} - domains: "${skipDomains}"`);
+
+ // Set the domain skip preference
+ Services.prefs.setCharPref("network.lna.skip-domains", skipDomains);
+
+ // Disable prompt simulation for clean testing
+ Services.prefs.setBoolPref("network.localhost.prompt.testing.allow", false);
+
+ let chan = makeChannel(url + "/test_lna");
+ chan.loadInfo.parentIpAddressSpace = parentSpace;
+
+ let expectFailure = expectedStatus !== Cr.NS_OK ? CL_EXPECT_FAILURE : 0;
+
+ await new Promise(resolve => {
+ chan.asyncOpen(new ChannelListener(resolve, null, expectFailure));
+ });
+
+ Assert.equal(
+ chan.status,
+ expectedStatus,
+ `Status should match for: ${description}`
+ );
+ if (expectedStatus === Cr.NS_OK) {
+ Assert.equal(chan.protocolVersion, url === H2_URL ? "h2" : "http/1.1");
+ }
+ }
+
+ // Cleanup
+ Services.prefs.clearUserPref("network.lna.skip-domains");
+ Services.prefs.clearUserPref("network.lna.address_space.private.override");
+ override.clearOverrides();
+ Services.dns.clearCache(true);
+});