summaryrefslogtreecommitdiffstats
path: root/netwerk
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
commit8dd16259287f58f9273002717ec4d27e97127719 (patch)
tree3863e62a53829a84037444beab3abd4ed9dfc7d0 /netwerk
parentReleasing progress-linux version 126.0.1-1~progress7.99u1. (diff)
downloadfirefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz
firefox-8dd16259287f58f9273002717ec4d27e97127719.zip
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--netwerk/base/FuzzySocketControl.cpp6
-rw-r--r--netwerk/base/LoadInfo.cpp48
-rw-r--r--netwerk/base/NetworkConnectivityService.cpp45
-rw-r--r--netwerk/base/NetworkConnectivityService.h18
-rw-r--r--netwerk/base/nsIClassOfService.idl4
-rw-r--r--netwerk/base/nsINetAddr.idl2
-rw-r--r--netwerk/base/nsINetworkConnectivityService.idl2
-rw-r--r--netwerk/base/nsINetworkInterceptController.idl2
-rw-r--r--netwerk/base/nsIOService.cpp2
-rw-r--r--netwerk/base/nsIServerSocket.idl2
-rw-r--r--netwerk/base/nsITLSServerSocket.idl2
-rw-r--r--netwerk/base/nsITimedChannel.idl4
-rw-r--r--netwerk/base/nsIUDPSocket.idl8
-rw-r--r--netwerk/base/nsProtocolProxyService.cpp4
-rw-r--r--netwerk/build/components.conf1
-rw-r--r--netwerk/cache2/CacheFileIOManager.cpp44
-rw-r--r--netwerk/cache2/CacheFileIOManager.h8
-rw-r--r--netwerk/cache2/CacheFileInputStream.cpp1
-rw-r--r--netwerk/cache2/CacheFileMetadata.cpp6
-rw-r--r--netwerk/cache2/CacheFileOutputStream.cpp2
-rw-r--r--netwerk/cache2/CacheIndex.cpp14
-rw-r--r--netwerk/cookie/CookieCommons.cpp42
-rw-r--r--netwerk/cookie/CookieService.cpp207
-rw-r--r--netwerk/cookie/CookieService.h1
-rw-r--r--netwerk/cookie/CookieServiceChild.cpp140
-rw-r--r--netwerk/cookie/CookieServiceParent.cpp35
-rw-r--r--netwerk/cookie/test/browser/browser.toml6
-rw-r--r--netwerk/cookie/test/browser/browser_cookie_chips.js539
-rw-r--r--netwerk/cookie/test/browser/browser_cookies_serviceWorker.js540
-rw-r--r--netwerk/cookie/test/browser/chips.sjs28
-rw-r--r--netwerk/cookie/test/browser/cookies.sjs17
-rw-r--r--netwerk/cookie/test/browser/serviceWorker.js21
-rw-r--r--netwerk/dns/DNS.cpp34
-rw-r--r--netwerk/dns/PlatformDNSAndroid.cpp4
-rw-r--r--netwerk/dns/PlatformDNSUnix.cpp4
-rw-r--r--netwerk/dns/PlatformDNSWin.cpp7
-rw-r--r--netwerk/dns/TRRService.cpp7
-rw-r--r--netwerk/dns/TRRService.h2
-rw-r--r--netwerk/dns/TRRServiceBase.cpp3
-rw-r--r--netwerk/dns/TRRServiceBase.h1
-rw-r--r--netwerk/dns/effective_tld_names.dat650
-rw-r--r--netwerk/dns/nsDNSService2.cpp18
-rw-r--r--netwerk/dns/nsDNSService2.h2
-rw-r--r--netwerk/dns/nsHostResolver.cpp14
-rw-r--r--netwerk/dns/nsHostResolver.h2
-rw-r--r--netwerk/dns/nsIDNSByTypeRecord.idl6
-rw-r--r--netwerk/dns/nsIDNSRecord.idl4
-rw-r--r--netwerk/dns/nsIDNSService.idl4
-rw-r--r--netwerk/ipc/DocumentLoadListener.h2
-rw-r--r--netwerk/locales/en-US/necko.properties2
-rw-r--r--netwerk/metrics.yaml44
-rw-r--r--netwerk/protocol/about/nsAboutProtocolHandler.cpp11
-rw-r--r--netwerk/protocol/data/nsDataHandler.cpp14
-rw-r--r--netwerk/protocol/http/ConnectionEntry.cpp3
-rw-r--r--netwerk/protocol/http/Http3WebTransportSession.cpp10
-rw-r--r--netwerk/protocol/http/HttpBaseChannel.cpp15
-rw-r--r--netwerk/protocol/http/HttpBaseChannel.h8
-rw-r--r--netwerk/protocol/http/HttpChannelChild.cpp8
-rw-r--r--netwerk/protocol/http/HttpChannelChild.h3
-rw-r--r--netwerk/protocol/http/NullHttpChannel.cpp10
-rw-r--r--netwerk/protocol/http/ObliviousHttpChannel.cpp10
-rw-r--r--netwerk/protocol/http/nsHttpChannel.cpp135
-rw-r--r--netwerk/protocol/http/nsHttpChannel.h5
-rw-r--r--netwerk/protocol/http/nsHttpConnection.cpp8
-rw-r--r--netwerk/protocol/http/nsHttpConnectionMgr.cpp36
-rw-r--r--netwerk/protocol/http/nsHttpHandler.cpp20
-rw-r--r--netwerk/protocol/http/nsHttpTransaction.cpp24
-rw-r--r--netwerk/protocol/http/nsHttpTransaction.h6
-rw-r--r--netwerk/protocol/http/nsIHttpChannel.idl8
-rw-r--r--netwerk/protocol/http/nsIHttpChannelInternal.idl2
-rw-r--r--netwerk/protocol/res/SubstitutingProtocolHandler.cpp8
-rw-r--r--netwerk/protocol/res/SubstitutingProtocolHandler.h12
-rw-r--r--netwerk/protocol/res/nsResProtocolHandler.cpp17
-rw-r--r--netwerk/protocol/res/nsResProtocolHandler.h8
-rw-r--r--netwerk/protocol/viewsource/nsViewSourceChannel.cpp12
-rw-r--r--netwerk/protocol/websocket/nsIWebSocketChannel.idl2
-rw-r--r--netwerk/protocol/webtransport/WebTransportSessionProxy.cpp1
-rw-r--r--netwerk/protocol/webtransport/WebTransportSessionProxy.h17
-rw-r--r--netwerk/protocol/webtransport/nsIWebTransport.idl25
-rw-r--r--netwerk/socket/neqo_glue/Cargo.toml12
-rw-r--r--netwerk/socket/neqo_glue/src/lib.rs30
-rw-r--r--netwerk/socket/nsINamedPipeService.idl4
-rw-r--r--netwerk/system/android/nsAndroidNetworkLinkService.cpp1
-rw-r--r--netwerk/system/linux/nsNetworkLinkService.cpp1
-rw-r--r--netwerk/system/win32/nsNotifyAddrListener.cpp2
-rw-r--r--netwerk/test/browser/browser.toml3
-rw-r--r--netwerk/test/browser/browser_dns_prefetch_link_header.js282
-rw-r--r--netwerk/test/browser/file_link_dns_prefetch.sjs25
-rw-r--r--netwerk/test/gtest/TestCommon.h8
-rw-r--r--netwerk/test/gtest/TestCookie.cpp4
-rw-r--r--netwerk/test/gtest/TestIDNA.cpp43
-rw-r--r--netwerk/test/gtest/TestInputStreamTransport.cpp2
-rw-r--r--netwerk/test/gtest/TestNamedPipeService.cpp2
-rw-r--r--netwerk/test/gtest/moz.build14
-rw-r--r--netwerk/test/http3server/Cargo.toml10
-rw-r--r--netwerk/test/unit/head_channels.js2
-rw-r--r--netwerk/test/unit/test_cookies_privatebrowsing.js13
-rw-r--r--netwerk/test/unit/test_dns_override.js25
-rw-r--r--netwerk/test/unit/test_httpssvc_iphint.js4
-rw-r--r--netwerk/test/unit/test_verify_traffic.js39
-rw-r--r--netwerk/test/unit/xpcshell.toml2
-rw-r--r--netwerk/wifi/gtest/TestWifiMonitor.cpp4
102 files changed, 2856 insertions, 725 deletions
diff --git a/netwerk/base/FuzzySocketControl.cpp b/netwerk/base/FuzzySocketControl.cpp
index ff53358417..77a7ed3ac8 100644
--- a/netwerk/base/FuzzySocketControl.cpp
+++ b/netwerk/base/FuzzySocketControl.cpp
@@ -124,6 +124,12 @@ NS_IMETHODIMP
FuzzySocketControl::StartTLS() { return NS_OK; }
NS_IMETHODIMP
+FuzzySocketControl::AsyncStartTLS(JSContext* aCx,
+ mozilla::dom::Promise** aPromise) {
+ return NS_OK;
+}
+
+NS_IMETHODIMP
FuzzySocketControl::SetNPNList(nsTArray<nsCString>& protocolArray) {
return NS_OK;
}
diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
index 6be031113f..7a9f8905b6 100644
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -423,20 +423,47 @@ LoadInfo::LoadInfo(dom::CanonicalBrowsingContext* aBrowsingContext,
}
#endif
- // If we think we should not resist fingerprinting, defer to the opener's
- // RFP bit (if there is an opener.) If the opener is also exempted, it stays
- // true, otherwise we will put a false into the CJS and that will be respected
- // on this document.
+ // This code path can be taken when loading an about:blank document, which
+ // means we might think that we should be exempted from resist fingerprinting.
+ // If we think that, we should defer to any opener, if it is present. If the
+ // opener is also exempted, then it continues to be exempted. Regardless of
+ // what ShouldRFP says, we _also_ need to propagate any RandomizationKey we
+ // have.
bool shouldResistFingerprinting =
nsContentUtils::ShouldResistFingerprinting_dangerous(
aURI, mOriginAttributes,
"We are creating CookieJarSettings, so we can't have one already.",
RFPTarget::IsAlwaysEnabledForPrecompute);
+
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+ nsTArray<uint8_t> randomKey;
RefPtr<BrowsingContext> opener = aBrowsingContext->GetOpener();
- if (!shouldResistFingerprinting && opener &&
- opener->GetCurrentWindowContext()) {
- shouldResistFingerprinting =
- opener->GetCurrentWindowContext()->ShouldResistFingerprinting();
+ if (opener) {
+ MOZ_ASSERT(opener->GetCurrentWindowContext());
+ if (opener->GetCurrentWindowContext()) {
+ shouldResistFingerprinting |=
+ opener->GetCurrentWindowContext()->ShouldResistFingerprinting();
+ }
+
+ // In the parent, we need to get the CJS from the CanonicalBrowsingContext's
+ // WindowGlobalParent If we're in the child, we probably have a reference to
+ // the opener's document, and can get it from there.
+ if (XRE_IsParentProcess()) {
+ MOZ_ASSERT(opener->Canonical()->GetCurrentWindowGlobal());
+ if (opener->Canonical()->GetCurrentWindowGlobal()) {
+ MOZ_ASSERT(
+ opener->Canonical()->GetCurrentWindowGlobal()->CookieJarSettings());
+ rv = opener->Canonical()
+ ->GetCurrentWindowGlobal()
+ ->CookieJarSettings()
+ ->GetFingerprintingRandomizationKey(randomKey);
+ }
+ } else if (opener->GetDocument()) {
+ MOZ_ASSERT(false, "Code is in child");
+ rv = opener->GetDocument()
+ ->CookieJarSettings()
+ ->GetFingerprintingRandomizationKey(randomKey);
+ }
}
const bool isPrivate = mOriginAttributes.mPrivateBrowsingId > 0;
@@ -447,6 +474,11 @@ LoadInfo::LoadInfo(dom::CanonicalBrowsingContext* aBrowsingContext,
mCookieJarSettings = CookieJarSettings::Create(
isPrivate ? CookieJarSettings::ePrivate : CookieJarSettings::eRegular,
shouldResistFingerprinting);
+
+ if (NS_SUCCEEDED(rv)) {
+ net::CookieJarSettings::Cast(mCookieJarSettings)
+ ->SetFingerprintingRandomizationKey(randomKey);
+ }
}
LoadInfo::LoadInfo(dom::WindowGlobalParent* aParentWGP,
diff --git a/netwerk/base/NetworkConnectivityService.cpp b/netwerk/base/NetworkConnectivityService.cpp
index 1e126742ce..2f3b80b724 100644
--- a/netwerk/base/NetworkConnectivityService.cpp
+++ b/netwerk/base/NetworkConnectivityService.cpp
@@ -4,6 +4,7 @@
#include "DNSUtils.h"
#include "NetworkConnectivityService.h"
+#include "mozilla/AppShutdown.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/net/SocketProcessParent.h"
#include "mozilla/Preferences.h"
@@ -30,14 +31,6 @@ NS_IMPL_ISUPPORTS(NetworkConnectivityService, nsIDNSListener, nsIObserver,
static StaticRefPtr<NetworkConnectivityService> gConnService;
-NetworkConnectivityService::NetworkConnectivityService()
- : mDNSv4(UNKNOWN),
- mDNSv6(UNKNOWN),
- mIPv4(UNKNOWN),
- mIPv6(UNKNOWN),
- mNAT64(UNKNOWN),
- mLock("nat64prefixes") {}
-
// static
already_AddRefed<NetworkConnectivityService>
NetworkConnectivityService::GetSingleton() {
@@ -45,6 +38,10 @@ NetworkConnectivityService::GetSingleton() {
return do_AddRef(gConnService);
}
+ if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
+ return nullptr;
+ }
+
RefPtr<NetworkConnectivityService> service = new NetworkConnectivityService();
service->Init();
@@ -60,6 +57,8 @@ nsresult NetworkConnectivityService::Init() {
observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC, false);
observerService->AddObserver(this, "network:captive-portal-connectivity",
false);
+ observerService->AddObserver(this, "browser-idle-startup-tasks-finished",
+ false);
return NS_OK;
}
@@ -79,6 +78,13 @@ NetworkConnectivityService::GetDNSv6(ConnectivityState* aState) {
}
NS_IMETHODIMP
+NetworkConnectivityService::GetDNS_HTTPS(ConnectivityState* aState) {
+ NS_ENSURE_ARG(aState);
+ *aState = mDNS_HTTPS;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
NetworkConnectivityService::GetIPv4(ConnectivityState* aState) {
NS_ENSURE_ARG(aState);
*aState = mIPv4;
@@ -154,6 +160,7 @@ static inline bool NAT64PrefixCompare(const NetAddr& prefix1,
void NetworkConnectivityService::PerformChecks() {
mDNSv4 = UNKNOWN;
mDNSv6 = UNKNOWN;
+ mDNS_HTTPS = UNKNOWN;
mIPv4 = UNKNOWN;
mIPv6 = UNKNOWN;
@@ -281,12 +288,16 @@ NetworkConnectivityService::OnLookupComplete(nsICancelable* aRequest,
} else if (aRequest == mDNSv6Request) {
mDNSv6 = state;
mDNSv6Request = nullptr;
+ } else if (aRequest == mDNS_HTTPSRequest) {
+ mDNS_HTTPS = state;
+ mDNS_HTTPSRequest = nullptr;
} else if (aRequest == mNAT64Request) {
mNAT64Request = nullptr;
SaveNAT64Prefixes(aRecord);
}
- if (!mDNSv4Request && !mDNSv6Request && !mNAT64Request) {
+ if (!mDNSv4Request && !mDNSv6Request && !mDNS_HTTPSRequest &&
+ !mNAT64Request) {
NotifyObservers("network:connectivity-service:dns-checks-complete");
}
return NS_OK;
@@ -328,6 +339,16 @@ NetworkConnectivityService::RecheckDNS() {
getter_AddRefs(mDNSv6Request));
NS_ENSURE_SUCCESS(rv, rv);
+ Preferences::GetCString("network.connectivity-service.DNS_HTTPS.domain",
+ host);
+ rv = dns->AsyncResolveNative(host, nsIDNSService::RESOLVE_TYPE_HTTPSSVC,
+ nsIDNSService::RESOLVE_TRR_DISABLED_MODE,
+ nullptr, this, NS_GetCurrentThread(), attrs,
+ getter_AddRefs(mDNS_HTTPSRequest));
+ if (NS_FAILED(rv)) {
+ mDNS_HTTPSRequest = nullptr;
+ }
+
if (StaticPrefs::network_connectivity_service_nat64_check()) {
rv = dns->AsyncResolveNative("ipv4only.arpa"_ns,
nsIDNSService::RESOLVE_TYPE_DEFAULT,
@@ -355,6 +376,10 @@ NetworkConnectivityService::Observe(nsISupports* aSubject, const char* aTopic,
mDNSv6Request->Cancel(NS_ERROR_ABORT);
mDNSv6Request = nullptr;
}
+ if (mDNS_HTTPSRequest) {
+ mDNS_HTTPSRequest->Cancel(NS_ERROR_ABORT);
+ mDNS_HTTPSRequest = nullptr;
+ }
if (mNAT64Request) {
mNAT64Request->Cancel(NS_ERROR_ABORT);
mNAT64Request = nullptr;
@@ -370,6 +395,8 @@ NetworkConnectivityService::Observe(nsISupports* aSubject, const char* aTopic,
!NS_LITERAL_STRING_FROM_CSTRING(NS_NETWORK_LINK_DATA_UNKNOWN)
.Equals(aData)) {
PerformChecks();
+ } else if (!strcmp(aTopic, "browser-idle-startup-tasks-finished")) {
+ PerformChecks();
}
return NS_OK;
diff --git a/netwerk/base/NetworkConnectivityService.h b/netwerk/base/NetworkConnectivityService.h
index 6315fb192b..b29825d5d5 100644
--- a/netwerk/base/NetworkConnectivityService.h
+++ b/netwerk/base/NetworkConnectivityService.h
@@ -33,7 +33,7 @@ class NetworkConnectivityService : public nsINetworkConnectivityService,
static already_AddRefed<NetworkConnectivityService> GetSingleton();
private:
- NetworkConnectivityService();
+ NetworkConnectivityService() = default;
virtual ~NetworkConnectivityService() = default;
nsresult Init();
@@ -47,18 +47,20 @@ class NetworkConnectivityService : public nsINetworkConnectivityService,
// Will be set to OK if the DNS request returned in IP of this type,
// NOT_AVAILABLE if that type of resolution is not available
// UNKNOWN if the check wasn't performed
- Atomic<ConnectivityState, Relaxed> mDNSv4;
- Atomic<ConnectivityState, Relaxed> mDNSv6;
+ Atomic<ConnectivityState, Relaxed> mDNSv4{ConnectivityState::UNKNOWN};
+ Atomic<ConnectivityState, Relaxed> mDNSv6{ConnectivityState::UNKNOWN};
+ Atomic<ConnectivityState, Relaxed> mDNS_HTTPS{ConnectivityState::UNKNOWN};
- Atomic<ConnectivityState, Relaxed> mIPv4;
- Atomic<ConnectivityState, Relaxed> mIPv6;
+ Atomic<ConnectivityState, Relaxed> mIPv4{ConnectivityState::UNKNOWN};
+ Atomic<ConnectivityState, Relaxed> mIPv6{ConnectivityState::UNKNOWN};
- Atomic<ConnectivityState, Relaxed> mNAT64;
+ Atomic<ConnectivityState, Relaxed> mNAT64{ConnectivityState::UNKNOWN};
- nsTArray<NetAddr> mNAT64Prefixes;
+ nsTArray<NetAddr> mNAT64Prefixes{ConnectivityState::UNKNOWN};
nsCOMPtr<nsICancelable> mDNSv4Request;
nsCOMPtr<nsICancelable> mDNSv6Request;
+ nsCOMPtr<nsICancelable> mDNS_HTTPSRequest;
nsCOMPtr<nsICancelable> mNAT64Request;
nsCOMPtr<nsIChannel> mIPv4Channel;
@@ -67,7 +69,7 @@ class NetworkConnectivityService : public nsINetworkConnectivityService,
bool mCheckedNetworkId = false;
bool mHasNetworkId = false;
- Mutex mLock MOZ_UNANNOTATED;
+ Mutex mLock MOZ_UNANNOTATED{"nat64prefixes"};
};
} // namespace net
diff --git a/netwerk/base/nsIClassOfService.idl b/netwerk/base/nsIClassOfService.idl
index 7b133107de..2d5fa03dc1 100644
--- a/netwerk/base/nsIClassOfService.idl
+++ b/netwerk/base/nsIClassOfService.idl
@@ -22,7 +22,7 @@ class ClassOfService;
%}
native ClassOfService(mozilla::net::ClassOfService);
-[scriptable, uuid(1ccb58ec-5e07-4cf9-a30d-ac5490d23b41)]
+[scriptable, builtinclass, uuid(1ccb58ec-5e07-4cf9-a30d-ac5490d23b41)]
interface nsIClassOfService : nsISupports
{
attribute unsigned long classFlags;
@@ -30,7 +30,7 @@ interface nsIClassOfService : nsISupports
void clearClassFlags(in unsigned long flags);
void addClassFlags(in unsigned long flags);
- void setClassOfService(in ClassOfService s);
+ [noscript] void setClassOfService(in ClassOfService s);
// All these flags have a (de)prioritization effect.
diff --git a/netwerk/base/nsINetAddr.idl b/netwerk/base/nsINetAddr.idl
index bbbcd28c0e..3e86442415 100644
--- a/netwerk/base/nsINetAddr.idl
+++ b/netwerk/base/nsINetAddr.idl
@@ -21,7 +21,7 @@ native NetAddr(mozilla::net::NetAddr);
* This interface represents a native NetAddr struct in a readonly
* interface.
*/
-[scriptable, uuid(652B9EC5-D159-45D7-9127-50BB559486CD)]
+[scriptable, builtinclass, uuid(652B9EC5-D159-45D7-9127-50BB559486CD)]
interface nsINetAddr : nsISupports
{
/**
diff --git a/netwerk/base/nsINetworkConnectivityService.idl b/netwerk/base/nsINetworkConnectivityService.idl
index 482eaf45ee..126e85b3fa 100644
--- a/netwerk/base/nsINetworkConnectivityService.idl
+++ b/netwerk/base/nsINetworkConnectivityService.idl
@@ -25,6 +25,8 @@ interface nsINetworkConnectivityService : nsISupports
readonly attribute nsINetworkConnectivityService_ConnectivityState DNSv4;
[infallible]
readonly attribute nsINetworkConnectivityService_ConnectivityState DNSv6;
+ [infallible]
+ readonly attribute nsINetworkConnectivityService_ConnectivityState DNS_HTTPS;
/* If connecting to IPv4/v6 works on the current network */
[infallible]
diff --git a/netwerk/base/nsINetworkInterceptController.idl b/netwerk/base/nsINetworkInterceptController.idl
index 946cc95a88..7f91d2df6f 100644
--- a/netwerk/base/nsINetworkInterceptController.idl
+++ b/netwerk/base/nsINetworkInterceptController.idl
@@ -48,7 +48,7 @@ interface nsIInterceptedBodyCallback : nsISupports
* which do not implement nsIChannel.
*/
-[scriptable, uuid(f4b82975-6a86-4cc4-87fe-9a1fd430c86d)]
+[scriptable, builtinclass, uuid(f4b82975-6a86-4cc4-87fe-9a1fd430c86d)]
interface nsIInterceptedChannel : nsISupports
{
/**
diff --git a/netwerk/base/nsIOService.cpp b/netwerk/base/nsIOService.cpp
index 998c389ace..07dde50227 100644
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -414,7 +414,7 @@ nsresult nsIOService::InitializeCaptivePortalService() {
mCaptivePortalService = do_GetService(NS_CAPTIVEPORTAL_CID);
if (mCaptivePortalService) {
- return static_cast<CaptivePortalService*>(mCaptivePortalService.get())
+ static_cast<CaptivePortalService*>(mCaptivePortalService.get())
->Initialize();
}
diff --git a/netwerk/base/nsIServerSocket.idl b/netwerk/base/nsIServerSocket.idl
index d6fd348778..3c21bdb707 100644
--- a/netwerk/base/nsIServerSocket.idl
+++ b/netwerk/base/nsIServerSocket.idl
@@ -19,7 +19,7 @@ typedef unsigned long nsServerSocketFlag;
*
* An interface to a server socket that can accept incoming connections.
*/
-[scriptable, uuid(7a9c39cb-a13f-4eef-9bdf-a74301628742)]
+[scriptable, builtinclass, uuid(7a9c39cb-a13f-4eef-9bdf-a74301628742)]
interface nsIServerSocket : nsISupports
{
/**
diff --git a/netwerk/base/nsITLSServerSocket.idl b/netwerk/base/nsITLSServerSocket.idl
index e944f23af7..a3588ddce2 100644
--- a/netwerk/base/nsITLSServerSocket.idl
+++ b/netwerk/base/nsITLSServerSocket.idl
@@ -8,7 +8,7 @@ interface nsIX509Cert;
interface nsITLSServerSecurityObserver;
interface nsISocketTransport;
-[scriptable, uuid(cc2c30f9-cfaa-4b8a-bd44-c24881981b74)]
+[scriptable, builtinclass, uuid(cc2c30f9-cfaa-4b8a-bd44-c24881981b74)]
interface nsITLSServerSocket : nsIServerSocket
{
/**
diff --git a/netwerk/base/nsITimedChannel.idl b/netwerk/base/nsITimedChannel.idl
index 4707bf1b7a..f6d85cf945 100644
--- a/netwerk/base/nsITimedChannel.idl
+++ b/netwerk/base/nsITimedChannel.idl
@@ -25,7 +25,7 @@ interface nsIServerTiming : nsISupports {
[ref] native nsServerTimingArrayRef(nsTArray<nsCOMPtr<nsIServerTiming>>);
// All properties return zero if the value is not available
-[scriptable, uuid(ca63784d-959c-4c3a-9a59-234a2a520de0)]
+[scriptable, builtinclass, uuid(ca63784d-959c-4c3a-9a59-234a2a520de0)]
interface nsITimedChannel : nsISupports {
// Set this attribute to true to enable collection of timing data.
// channelCreationTime will be available even with this attribute set to
@@ -124,5 +124,5 @@ interface nsITimedChannel : nsISupports {
[noscript] attribute boolean reportResourceTiming;
readonly attribute nsIArray serverTiming;
- nsServerTimingArrayRef getNativeServerTiming();
+ [noscript] nsServerTimingArrayRef getNativeServerTiming();
};
diff --git a/netwerk/base/nsIUDPSocket.idl b/netwerk/base/nsIUDPSocket.idl
index 5c23c1bb6f..d07be55349 100644
--- a/netwerk/base/nsIUDPSocket.idl
+++ b/netwerk/base/nsIUDPSocket.idl
@@ -31,7 +31,7 @@ native NetAddr(mozilla::net::NetAddr);
*
* An interface to a UDP socket that can accept incoming connections.
*/
-[scriptable, uuid(d423bf4e-4499-40cf-bc03-153e2bf206d1)]
+[scriptable, builtinclass, uuid(d423bf4e-4499-40cf-bc03-153e2bf206d1)]
interface nsIUDPSocket : nsISupports
{
/**
@@ -126,7 +126,7 @@ interface nsIUDPSocket : nsISupports
* @param aRemoteAddr
* The remote address to connect to
*/
- void connect([const] in NetAddrPtr aAddr);
+ [noscript] void connect([const] in NetAddrPtr aAddr);
/**
* Returns the local address of this UDP socket
@@ -217,8 +217,8 @@ interface nsIUDPSocket : nsISupports
* @param addr The remote host address.
* @param stream The input stream to be sent. This must be a buffered stream implementation.
*/
- void sendBinaryStreamWithAddress([const] in NetAddrPtr addr,
- in nsIInputStream stream);
+ [noscript] void sendBinaryStreamWithAddress([const] in NetAddrPtr addr,
+ in nsIInputStream stream);
/**
* joinMulticast
diff --git a/netwerk/base/nsProtocolProxyService.cpp b/netwerk/base/nsProtocolProxyService.cpp
index 7ccfc9363a..743c977c74 100644
--- a/netwerk/base/nsProtocolProxyService.cpp
+++ b/netwerk/base/nsProtocolProxyService.cpp
@@ -2292,6 +2292,10 @@ void nsProtocolProxyService::MaybeDisableDNSPrefetch(nsIProxyInfo* aProxy) {
nsCOMPtr<nsProxyInfo> pi = do_QueryInterface(aProxy);
if (!pi || !pi->mType || pi->mType == kProxyType_DIRECT) return;
+ if (StaticPrefs::network_dns_prefetch_via_proxy()) {
+ return;
+ }
+
// To avoid getting DNS service recursively, we directly use
// GetXPCOMSingleton().
nsCOMPtr<nsIDNSService> dns = nsDNSService::GetXPCOMSingleton();
diff --git a/netwerk/build/components.conf b/netwerk/build/components.conf
index 68d7be7ec3..bebf9695e4 100644
--- a/netwerk/build/components.conf
+++ b/netwerk/build/components.conf
@@ -646,6 +646,7 @@ Classes = [
'@mozilla.org/streamconv;1?from=gzip&to=uncompressed',
'@mozilla.org/streamconv;1?from=x-compress&to=uncompressed',
'@mozilla.org/streamconv;1?from=x-gzip&to=uncompressed',
+ '@mozilla.org/streamconv;1?from=zstd&to=uncompressed',
],
'legacy_constructor': 'CreateNewHTTPCompressConvFactory',
'processes': ProcessSelector.ALLOW_IN_SOCKET_PROCESS,
diff --git a/netwerk/cache2/CacheFileIOManager.cpp b/netwerk/cache2/CacheFileIOManager.cpp
index 8cff1c1cd9..89cd4497ad 100644
--- a/netwerk/cache2/CacheFileIOManager.cpp
+++ b/netwerk/cache2/CacheFileIOManager.cpp
@@ -2026,26 +2026,46 @@ nsresult CacheFileIOManager::Write(CacheFileHandle* aHandle, int64_t aOffset,
"validate=%d, truncate=%d, listener=%p]",
aHandle, aOffset, aCount, aValidate, aTruncate, aCallback));
- nsresult rv;
+ MOZ_ASSERT(aCallback);
+
RefPtr<CacheFileIOManager> ioMan = gInstance;
- if (aHandle->IsClosed() || (aCallback && aCallback->IsKilled()) || !ioMan) {
- if (!aCallback) {
- // When no callback is provided, CacheFileIOManager is responsible for
- // releasing the buffer. We must release it even in case of failure.
- free(const_cast<char*>(aBuf));
- }
+ if (aHandle->IsClosed() || aCallback->IsKilled() || !ioMan) {
return NS_ERROR_NOT_INITIALIZED;
}
RefPtr<WriteEvent> ev = new WriteEvent(aHandle, aOffset, aBuf, aCount,
aValidate, aTruncate, aCallback);
- rv = ioMan->mIOThread->Dispatch(ev, aHandle->mPriority
- ? CacheIOThread::WRITE_PRIORITY
- : CacheIOThread::WRITE);
- NS_ENSURE_SUCCESS(rv, rv);
+ return ioMan->mIOThread->Dispatch(ev, aHandle->mPriority
+ ? CacheIOThread::WRITE_PRIORITY
+ : CacheIOThread::WRITE);
+}
- return NS_OK;
+// static
+nsresult CacheFileIOManager::WriteWithoutCallback(CacheFileHandle* aHandle,
+ int64_t aOffset, char* aBuf,
+ int32_t aCount,
+ bool aValidate,
+ bool aTruncate) {
+ LOG(("CacheFileIOManager::WriteWithoutCallback() [handle=%p, offset=%" PRId64
+ ", count=%d, "
+ "validate=%d, truncate=%d]",
+ aHandle, aOffset, aCount, aValidate, aTruncate));
+
+ RefPtr<CacheFileIOManager> ioMan = gInstance;
+
+ if (aHandle->IsClosed() || !ioMan) {
+ // When no callback is provided, CacheFileIOManager is responsible for
+ // releasing the buffer. We must release it even in case of failure.
+ free(aBuf);
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ RefPtr<WriteEvent> ev = new WriteEvent(aHandle, aOffset, aBuf, aCount,
+ aValidate, aTruncate, nullptr);
+ return ioMan->mIOThread->Dispatch(ev, aHandle->mPriority
+ ? CacheIOThread::WRITE_PRIORITY
+ : CacheIOThread::WRITE);
}
static nsresult TruncFile(PRFileDesc* aFD, int64_t aEOF) {
diff --git a/netwerk/cache2/CacheFileIOManager.h b/netwerk/cache2/CacheFileIOManager.h
index 5be21c8db8..67c67e718d 100644
--- a/netwerk/cache2/CacheFileIOManager.h
+++ b/netwerk/cache2/CacheFileIOManager.h
@@ -287,9 +287,17 @@ class CacheFileIOManager final : public nsITimerCallback, public nsINamed {
CacheFileIOListener* aCallback);
static nsresult Read(CacheFileHandle* aHandle, int64_t aOffset, char* aBuf,
int32_t aCount, CacheFileIOListener* aCallback);
+ // This function must be called with a callback. The caller is responsible for
+ // releasing |aBuf|.
static nsresult Write(CacheFileHandle* aHandle, int64_t aOffset,
const char* aBuf, int32_t aCount, bool aValidate,
bool aTruncate, CacheFileIOListener* aCallback);
+ // Similar to the above, but without the callback. Note that |aBuf| will be
+ // released by CacheFileIOManager.
+ static nsresult WriteWithoutCallback(CacheFileHandle* aHandle,
+ int64_t aOffset, char* aBuf,
+ int32_t aCount, bool aValidate,
+ bool aTruncate);
// PinningDoomRestriction:
// NO_RESTRICTION
// no restriction is checked, the file is simply always doomed
diff --git a/netwerk/cache2/CacheFileInputStream.cpp b/netwerk/cache2/CacheFileInputStream.cpp
index 99302baf54..564a08fd2b 100644
--- a/netwerk/cache2/CacheFileInputStream.cpp
+++ b/netwerk/cache2/CacheFileInputStream.cpp
@@ -8,6 +8,7 @@
#include "CacheFile.h"
#include "nsStreamUtils.h"
#include "nsThreadUtils.h"
+#include "mozilla/IntegerPrintfMacros.h"
#include <algorithm>
namespace mozilla::net {
diff --git a/netwerk/cache2/CacheFileMetadata.cpp b/netwerk/cache2/CacheFileMetadata.cpp
index 68d55b1988..5e299a7852 100644
--- a/netwerk/cache2/CacheFileMetadata.cpp
+++ b/netwerk/cache2/CacheFileMetadata.cpp
@@ -257,14 +257,16 @@ nsresult CacheFileMetadata::WriteMetadata(
char* writeBuffer = mWriteBuf;
if (aListener) {
mListener = aListener;
+ rv = CacheFileIOManager::Write(mHandle, aOffset, writeBuffer,
+ p - writeBuffer, true, true, this);
} else {
// We are not going to pass |this| as a callback so the buffer will be
// released by CacheFileIOManager. Just null out mWriteBuf here.
mWriteBuf = nullptr;
+ rv = CacheFileIOManager::WriteWithoutCallback(mHandle, aOffset, writeBuffer,
+ p - writeBuffer, true, true);
}
- rv = CacheFileIOManager::Write(mHandle, aOffset, writeBuffer, p - writeBuffer,
- true, true, aListener ? this : nullptr);
if (NS_FAILED(rv)) {
LOG(
("CacheFileMetadata::WriteMetadata() - CacheFileIOManager::Write() "
diff --git a/netwerk/cache2/CacheFileOutputStream.cpp b/netwerk/cache2/CacheFileOutputStream.cpp
index 985082efba..b541132bd9 100644
--- a/netwerk/cache2/CacheFileOutputStream.cpp
+++ b/netwerk/cache2/CacheFileOutputStream.cpp
@@ -9,7 +9,7 @@
#include "CacheEntry.h"
#include "nsStreamUtils.h"
#include "nsThreadUtils.h"
-#include "mozilla/DebugOnly.h"
+#include "mozilla/IntegerPrintfMacros.h"
#include <algorithm>
namespace mozilla::net {
diff --git a/netwerk/cache2/CacheIndex.cpp b/netwerk/cache2/CacheIndex.cpp
index c0cb63ef6d..34931087c0 100644
--- a/netwerk/cache2/CacheIndex.cpp
+++ b/netwerk/cache2/CacheIndex.cpp
@@ -2213,16 +2213,10 @@ void CacheIndex::ParseRecords(const StaticMutexAutoLock& aProofOfLock) {
reinterpret_cast<uint32_t*>(moz_xmalloc(sizeof(uint32_t)));
NetworkEndian::writeUint32(isDirty, 1);
- // Mark index dirty. The buffer is freed by CacheFileIOManager when
- // nullptr is passed as the listener and the call doesn't fail
- // synchronously.
- rv = CacheFileIOManager::Write(mIndexHandle, 2 * sizeof(uint32_t),
- reinterpret_cast<char*>(isDirty),
- sizeof(uint32_t), true, false, nullptr);
- if (NS_FAILED(rv)) {
- // This is not fatal, just free the memory
- free(isDirty);
- }
+ // Mark index dirty. The buffer will be freed by CacheFileIOManager.
+ CacheFileIOManager::WriteWithoutCallback(
+ mIndexHandle, 2 * sizeof(uint32_t), reinterpret_cast<char*>(isDirty),
+ sizeof(uint32_t), true, false);
}
pos += sizeof(uint32_t);
diff --git a/netwerk/cookie/CookieCommons.cpp b/netwerk/cookie/CookieCommons.cpp
index 9b26fc4a6e..4c4ae0c848 100644
--- a/netwerk/cookie/CookieCommons.cpp
+++ b/netwerk/cookie/CookieCommons.cpp
@@ -349,10 +349,6 @@ already_AddRefed<Cookie> CookieCommons::CreateCookieFromDocument(
std::function<bool(const nsACString&, const OriginAttributes&)>&&
aHasExistingCookiesLambda,
nsIURI** aDocumentURI, nsACString& aBaseDomain, OriginAttributes& aAttrs) {
- nsCOMPtr<nsIPrincipal> storagePrincipal =
- aDocument->EffectiveCookiePrincipal();
- MOZ_ASSERT(storagePrincipal);
-
nsCOMPtr<nsIURI> principalURI;
auto* basePrincipal = BasePrincipal::Cast(aDocument->NodePrincipal());
basePrincipal->GetURI(getter_AddRefs(principalURI));
@@ -379,15 +375,6 @@ already_AddRefed<Cookie> CookieCommons::CreateCookieFromDocument(
return nullptr;
}
- // Check if limit-foreign is required.
- uint32_t dummyRejectedReason = 0;
- if (aDocument->CookieJarSettings()->GetLimitForeignContexts() &&
- !aHasExistingCookiesLambda(baseDomain,
- storagePrincipal->OriginAttributesRef()) &&
- !ShouldAllowAccessFor(innerWindow, principalURI, &dummyRejectedReason)) {
- return nullptr;
- }
-
bool isForeignAndNotAddon = false;
if (!BasePrincipal::Cast(aDocument->NodePrincipal())->AddonPolicy()) {
rv = aThirdPartyUtil->IsThirdPartyWindow(
@@ -439,8 +426,29 @@ already_AddRefed<Cookie> CookieCommons::CreateCookieFromDocument(
return nullptr;
}
+ // CHIPS - If the partitioned attribute is set, store cookie in partitioned
+ // cookie jar independent of context. If the cookies are stored in the
+ // partitioned cookie jar anyway no special treatment of CHIPS cookies
+ // necessary.
+ bool needPartitioned =
+ StaticPrefs::network_cookie_cookieBehavior_optInPartitioning() &&
+ cookieData.isPartitioned();
+ nsCOMPtr<nsIPrincipal> cookiePrincipal =
+ needPartitioned ? aDocument->PartitionedPrincipal()
+ : aDocument->EffectiveCookiePrincipal();
+ MOZ_ASSERT(cookiePrincipal);
+
+ // Check if limit-foreign is required.
+ uint32_t dummyRejectedReason = 0;
+ if (aDocument->CookieJarSettings()->GetLimitForeignContexts() &&
+ !aHasExistingCookiesLambda(baseDomain,
+ cookiePrincipal->OriginAttributesRef()) &&
+ !ShouldAllowAccessFor(innerWindow, principalURI, &dummyRejectedReason)) {
+ return nullptr;
+ }
+
RefPtr<Cookie> cookie =
- Cookie::Create(cookieData, storagePrincipal->OriginAttributesRef());
+ Cookie::Create(cookieData, cookiePrincipal->OriginAttributesRef());
MOZ_ASSERT(cookie);
cookie->SetLastAccessed(currentTimeInUsec);
@@ -448,7 +456,7 @@ already_AddRefed<Cookie> CookieCommons::CreateCookieFromDocument(
Cookie::GenerateUniqueCreationTime(currentTimeInUsec));
aBaseDomain = baseDomain;
- aAttrs = storagePrincipal->OriginAttributesRef();
+ aAttrs = cookiePrincipal->OriginAttributesRef();
principalURI.forget(aDocumentURI);
return cookie.forget();
@@ -486,9 +494,11 @@ bool CookieCommons::ShouldIncludeCrossSiteCookieForDocument(
int32_t sameSiteAttr = 0;
aCookie->GetSameSite(&sameSiteAttr);
+ // CHIPS - If a third-party has storage access it can access both it's
+ // partitioned and unpartitioned cookie jars, else its cookies are blocked.
if (aDocument->CookieJarSettings()->GetPartitionForeign() &&
StaticPrefs::network_cookie_cookieBehavior_optInPartitioning() &&
- !aCookie->IsPartitioned()) {
+ !aCookie->IsPartitioned() && !aDocument->UsingStorageAccess()) {
return false;
}
diff --git a/netwerk/cookie/CookieService.cpp b/netwerk/cookie/CookieService.cpp
index 0e90b8cbae..78698d44a0 100644
--- a/netwerk/cookie/CookieService.cpp
+++ b/netwerk/cookie/CookieService.cpp
@@ -373,15 +373,6 @@ CookieService::GetCookieStringFromDocument(Document* aDocument,
return NS_OK;
}
- nsCOMPtr<nsIPrincipal> cookiePrincipal =
- aDocument->EffectiveCookiePrincipal();
-
- // TODO (Bug 1874174): A document could access both unpartitioned and
- // partitioned cookie jars. We will need to prepare partitioned and
- // unpartitioned principals for access both cookie jars.
- nsTArray<nsCOMPtr<nsIPrincipal>> principals;
- principals.AppendElement(cookiePrincipal);
-
bool thirdParty = true;
nsPIDOMWindowInner* innerWindow = aDocument->GetInnerWindow();
// in gtests we don't have a window, let's consider those requests as 3rd
@@ -395,6 +386,26 @@ CookieService::GetCookieStringFromDocument(Document* aDocument,
}
}
+ nsCOMPtr<nsIPrincipal> cookiePrincipal =
+ aDocument->EffectiveCookiePrincipal();
+
+ nsTArray<nsCOMPtr<nsIPrincipal>> principals;
+ principals.AppendElement(cookiePrincipal);
+
+ // CHIPS - If CHIPS is enabled the partitioned cookie jar is always available
+ // (and therefore the partitioned principal), the unpartitioned cookie jar is
+ // only available in first-party or third-party with storageAccess contexts.
+ bool isCHIPS = StaticPrefs::network_cookie_cookieBehavior_optInPartitioning();
+ bool isUnpartitioned =
+ cookiePrincipal->OriginAttributesRef().mPartitionKey.IsEmpty();
+ if (isCHIPS && isUnpartitioned) {
+ // Assert that we are only doing this if we are first-party or third-party
+ // with storageAccess.
+ MOZ_ASSERT(!thirdParty || aDocument->UsingStorageAccess());
+ // Add the partitioned principal to principals
+ principals.AppendElement(aDocument->PartitionedPrincipal());
+ }
+
nsTArray<Cookie*> cookieList;
for (auto& principal : principals) {
@@ -519,20 +530,40 @@ CookieService::GetCookieStringFromHttp(nsIURI* aHostURI, nsIChannel* aChannel,
ThirdPartyAnalysisResult result = mThirdPartyUtil->AnalyzeChannel(
aChannel, false, aHostURI, nullptr, &rejectedReason);
- OriginAttributes attrs;
- StoragePrincipalHelper::GetOriginAttributes(
- aChannel, attrs, StoragePrincipalHelper::eStorageAccessPrincipal);
-
bool isSafeTopLevelNav = CookieCommons::IsSafeTopLevelNav(aChannel);
bool hadCrossSiteRedirects = false;
bool isSameSiteForeign = CookieCommons::IsSameSiteForeign(
aChannel, aHostURI, &hadCrossSiteRedirects);
- // TODO (Bug 1874174): A channel could load both unpartitioned and partitioned
- // cookie jars together. We will need to get cookies from both unpartitioned
- // and partitioned cookie jars according to storage access.
+ OriginAttributes storageOriginAttributes;
+ StoragePrincipalHelper::GetOriginAttributes(
+ aChannel, storageOriginAttributes,
+ StoragePrincipalHelper::eStorageAccessPrincipal);
+
nsTArray<OriginAttributes> originAttributesList;
- originAttributesList.AppendElement(attrs);
+ originAttributesList.AppendElement(storageOriginAttributes);
+
+ // CHIPS - If CHIPS is enabled the partitioned cookie jar is always available
+ // (and therefore the partitioned OriginAttributes), the unpartitioned cookie
+ // jar is only available in first-party or third-party with storageAccess
+ // contexts.
+ bool isCHIPS = StaticPrefs::network_cookie_cookieBehavior_optInPartitioning();
+ bool isUnpartitioned = storageOriginAttributes.mPartitionKey.IsEmpty();
+ if (isCHIPS && isUnpartitioned) {
+ // Assert that we are only doing this if we are first-party or third-party
+ // with storageAccess.
+ MOZ_ASSERT(
+ !result.contains(ThirdPartyAnalysis::IsForeign) ||
+ result.contains(ThirdPartyAnalysis::IsStorageAccessPermissionGranted));
+ // Add the partitioned principal to principals
+ OriginAttributes partitionedOriginAttributes;
+ StoragePrincipalHelper::GetOriginAttributes(
+ aChannel, partitionedOriginAttributes,
+ StoragePrincipalHelper::ePartitionedPrincipal);
+ originAttributesList.AppendElement(partitionedOriginAttributes);
+ // Assert partitionedOAs have partitioneKey set.
+ MOZ_ASSERT(!partitionedOriginAttributes.mPartitionKey.IsEmpty());
+ }
AutoTArray<Cookie*, 8> foundCookieList;
GetCookiesForURI(
@@ -630,9 +661,10 @@ CookieService::SetCookieStringFromHttp(nsIURI* aHostURI,
ThirdPartyAnalysisResult result = mThirdPartyUtil->AnalyzeChannel(
aChannel, false, aHostURI, nullptr, &rejectedReason);
- OriginAttributes attrs;
+ OriginAttributes storagePrincipalOriginAttributes;
StoragePrincipalHelper::GetOriginAttributes(
- aChannel, attrs, StoragePrincipalHelper::eStorageAccessPrincipal);
+ aChannel, storagePrincipalOriginAttributes,
+ StoragePrincipalHelper::eStorageAccessPrincipal);
// get the base domain for the host URI.
// e.g. for "www.bbc.co.uk", this would be "bbc.co.uk".
@@ -660,11 +692,11 @@ CookieService::SetCookieStringFromHttp(nsIURI* aHostURI,
baseDomainFromURI);
NS_ENSURE_SUCCESS(rv, NS_OK);
- CookieStorage* storage = PickStorage(attrs);
+ CookieStorage* storage = PickStorage(storagePrincipalOriginAttributes);
// check default prefs
uint32_t priorCookieCount = storage->CountCookiesFromHost(
- baseDomainFromURI, attrs.mPrivateBrowsingId);
+ baseDomainFromURI, storagePrincipalOriginAttributes.mPrivateBrowsingId);
nsCOMPtr<nsIConsoleReportCollector> crc = do_QueryInterface(aChannel);
@@ -674,7 +706,8 @@ CookieService::SetCookieStringFromHttp(nsIURI* aHostURI,
result.contains(ThirdPartyAnalysis::IsThirdPartyTrackingResource),
result.contains(ThirdPartyAnalysis::IsThirdPartySocialTrackingResource),
result.contains(ThirdPartyAnalysis::IsStorageAccessPermissionGranted),
- aCookieHeader, priorCookieCount, attrs, &rejectedReason);
+ aCookieHeader, priorCookieCount, storagePrincipalOriginAttributes,
+ &rejectedReason);
MOZ_ASSERT_IF(rejectedReason, cookieStatus == STATUS_REJECTED);
@@ -718,9 +751,24 @@ CookieService::SetCookieStringFromHttp(nsIURI* aHostURI,
nsCString cookieHeader(aCookieHeader);
- bool moreCookieToRead = true;
+ // CHIPS - The partitioned cookie jar is always available and it is always
+ // possible to store cookies in it using the "Partitioned" attribute.
+ // Prepare the partitioned principals OAs to enable possible partitioned
+ // cookie storing from first-party or with StorageAccess.
+ // Similar behavior to CookieServiceChild::SetCookieStringFromHttp().
+ OriginAttributes partitionedPrincipalOriginAttributes;
+ bool isPartitionedPrincipal =
+ !storagePrincipalOriginAttributes.mPartitionKey.IsEmpty();
+ bool isCHIPS = StaticPrefs::network_cookie_cookieBehavior_optInPartitioning();
+ // Only need to get OAs if we don't already use the partitioned principal.
+ if (isCHIPS && !isPartitionedPrincipal) {
+ StoragePrincipalHelper::GetOriginAttributes(
+ aChannel, partitionedPrincipalOriginAttributes,
+ StoragePrincipalHelper::ePartitionedPrincipal);
+ }
// process each cookie in the header
+ bool moreCookieToRead = true;
while (moreCookieToRead) {
CookieStruct cookieData;
bool canSetCookie = false;
@@ -751,8 +799,22 @@ CookieService::SetCookieStringFromHttp(nsIURI* aHostURI,
continue;
}
+ // CHIPS - If the partitioned attribute is set, store cookie in partitioned
+ // cookie jar independent of context. If the cookies are stored in the
+ // partitioned cookie jar anyway no special treatment of CHIPS cookies
+ // necessary.
+ bool needPartitioned =
+ isCHIPS && cookieData.isPartitioned() && !isPartitionedPrincipal;
+ OriginAttributes& cookieOriginAttributes =
+ needPartitioned ? partitionedPrincipalOriginAttributes
+ : storagePrincipalOriginAttributes;
+ // Assert that partitionedPrincipalOriginAttributes are initialized if used.
+ MOZ_ASSERT_IF(
+ needPartitioned,
+ !partitionedPrincipalOriginAttributes.mPartitionKey.IsEmpty());
+
// create a new Cookie
- RefPtr<Cookie> cookie = Cookie::Create(cookieData, attrs);
+ RefPtr<Cookie> cookie = Cookie::Create(cookieData, cookieOriginAttributes);
MOZ_ASSERT(cookie);
int64_t currentTimeInUsec = PR_Now();
@@ -763,8 +825,8 @@ CookieService::SetCookieStringFromHttp(nsIURI* aHostURI,
RefPtr<BrowsingContext> bc = loadInfo->GetBrowsingContext();
// add the cookie to the list. AddCookie() takes care of logging.
- storage->AddCookie(crc, baseDomain, attrs, cookie, currentTimeInUsec,
- aHostURI, aCookieHeader, true, bc);
+ storage->AddCookie(crc, baseDomain, cookieOriginAttributes, cookie,
+ currentTimeInUsec, aHostURI, aCookieHeader, true, bc);
}
return NS_OK;
@@ -1180,6 +1242,16 @@ static void RecordPartitionedTelemetry(const CookieStruct& aCookieData,
}
}
+static bool HasSecurePrefix(const nsACString& aString) {
+ return StringBeginsWith(aString, "__Secure-"_ns,
+ nsCaseInsensitiveCStringComparator);
+}
+
+static bool HasHostPrefix(const nsACString& aString) {
+ return StringBeginsWith(aString, "__Host-"_ns,
+ nsCaseInsensitiveCStringComparator);
+}
+
// processes a single cookie, and returns true if there are more cookies
// to be processed
bool CookieService::CanSetCookie(
@@ -1290,9 +1362,12 @@ bool CookieService::CanSetCookie(
return newCookie;
}
- if (!CheckHiddenPrefix(aCookieData)) {
+ // If a cookie is nameless, then its value must not start with
+ // `__Host-` or `__Secure-`
+ if (aCookieData.name().IsEmpty() && (HasSecurePrefix(aCookieData.value()) ||
+ HasHostPrefix(aCookieData.value()))) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader,
- "failed the CheckHiddenPrefix tests");
+ "failed hidden prefix tests");
CookieLogging::LogMessageToConsole(
aCRC, aHostURI, nsIScriptError::warningFlag, CONSOLE_REJECTION_CATEGORY,
"CookieRejectedInvalidPrefix"_ns,
@@ -1449,10 +1524,9 @@ bool CookieService::CanSetCookie(
separators = ";" | "="
value-sep = ";"
cookie-sep = CR | LF
- allowed-chars = <any OCTET except NUL or cookie-sep>
+ allowed-chars = <any OCTET except cookie-sep>
OCTET = <any 8-bit sequence of data>
LWS = SP | HT
- NUL = <US-ASCII NUL, null control character (0)>
CR = <US-ASCII CR, carriage return (13)>
LF = <US-ASCII LF, linefeed (10)>
SP = <US-ASCII SP, space (32)>
@@ -1472,6 +1546,8 @@ bool CookieService::CanSetCookie(
| "Max-Age" "=" value
| "Comment" "=" value
| "Version" "=" value
+ | "Partitioned"
+ | "SameSite"
| "Secure"
| "HttpOnly"
@@ -1479,7 +1555,6 @@ bool CookieService::CanSetCookie(
// clang-format on
// helper functions for GetTokenValue
-static inline bool isnull(char c) { return c == 0; }
static inline bool iswhitespace(char c) { return c == ' ' || c == '\t'; }
static inline bool isterminator(char c) { return c == '\n' || c == '\r'; }
static inline bool isvalueseparator(char c) {
@@ -1507,7 +1582,7 @@ bool CookieService::GetTokenValue(nsACString::const_char_iterator& aIter,
++aIter;
}
start = aIter;
- while (aIter != aEndIter && !isnull(*aIter) && !istokenseparator(*aIter)) {
+ while (aIter != aEndIter && !istokenseparator(*aIter)) {
++aIter;
}
@@ -1530,7 +1605,7 @@ bool CookieService::GetTokenValue(nsACString::const_char_iterator& aIter,
// process <token>
// just look for ';' to terminate ('=' allowed)
- while (aIter != aEndIter && !isnull(*aIter) && !isvalueseparator(*aIter)) {
+ while (aIter != aEndIter && !isvalueseparator(*aIter)) {
++aIter;
}
@@ -1549,6 +1624,21 @@ bool CookieService::GetTokenValue(nsACString::const_char_iterator& aIter,
// if on terminator, increment past & return true to process new cookie
if (isterminator(*aIter)) {
++aIter;
+ while (aIter != aEndIter && isvalueseparator(*aIter)) {
+ ++aIter;
+ }
+ nsACString::const_char_iterator end = aIter - 1;
+ if (!isterminator(*end)) {
+ // The cookie isn't valid because we have multiple terminators or
+ // a terminator followed by a value separator. Add those invalid
+ // characters to the cookie string or value so it will be rejected.
+ if (aEqualsFound) {
+ aTokenString.Rebind(start, end);
+ } else {
+ aTokenValue.Rebind(start, end);
+ }
+ return false;
+ }
return true;
}
// fall-through: aIter is on ';', increment and return false
@@ -1570,6 +1660,17 @@ static inline void SetSameSiteAttribute(CookieStruct& aCookieData,
aCookieData.rawSameSite() = aValue;
}
+// Tests for control characters, defined by RFC 5234 to be %x00-1F / %x7F.
+// An exception is made for HTAB as the cookie spec treats that as whitespace.
+static bool ContainsControlChars(const nsACString& aString) {
+ const auto* start = aString.BeginReading();
+ const auto* end = aString.EndReading();
+
+ return std::find_if(start, end, [](unsigned char c) {
+ return (c <= 0x1F && c != 0x09) || c == 0x7F;
+ }) != end;
+}
+
// Parses attributes from cookie header. expires/max-age attributes aren't
// folded into the cookie struct here, because we don't know which one to use
// until we've parsed the header.
@@ -1627,6 +1728,14 @@ bool CookieService::ParseAttributes(nsIConsoleReportCollector* aCRC,
newCookie = GetTokenValue(cookieStart, cookieEnd, tokenString, tokenValue,
equalsFound);
+ if (ContainsControlChars(tokenString) || ContainsControlChars(tokenValue)) {
+ CookieLogging::LogMessageToConsole(
+ aCRC, aHostURI, nsIScriptError::errorFlag, CONSOLE_REJECTION_CATEGORY,
+ "CookieRejectedInvalidCharAttributes"_ns,
+ AutoTArray<nsString, 1>{NS_ConvertUTF8toUTF16(aCookieData.name())});
+ return newCookie;
+ }
+
// decide which attribute we have, and copy the string
if (tokenString.LowerCaseEqualsLiteral(kPath)) {
aCookieData.path() = tokenValue;
@@ -1967,25 +2076,6 @@ bool CookieService::CheckDomain(CookieStruct& aCookieData, nsIURI* aHostURI,
return true;
}
-// static
-bool CookieService::CheckHiddenPrefix(CookieStruct& aCookieData) {
- // If a cookie is nameless, then its value must not start with
- // `__Host-` or `__Secure-`
- if (!aCookieData.name().IsEmpty()) {
- return true;
- }
-
- if (StringBeginsWith(aCookieData.value(), "__Host-"_ns)) {
- return false;
- }
-
- if (StringBeginsWith(aCookieData.value(), "__Secure-"_ns)) {
- return false;
- }
-
- return true;
-}
-
namespace {
nsAutoCString GetPathFromURI(nsIURI* aHostURI) {
// strip down everything after the last slash to get the path,
@@ -2053,15 +2143,10 @@ bool CookieService::CheckPath(CookieStruct& aCookieData,
// regularized and validated the CookieStruct values!
bool CookieService::CheckPrefixes(CookieStruct& aCookieData,
bool aSecureRequest) {
- static const char kSecure[] = "__Secure-";
- static const char kHost[] = "__Host-";
- static const int kSecureLen = sizeof(kSecure) - 1;
- static const int kHostLen = sizeof(kHost) - 1;
-
- bool isSecure = strncmp(aCookieData.name().get(), kSecure, kSecureLen) == 0;
- bool isHost = strncmp(aCookieData.name().get(), kHost, kHostLen) == 0;
+ bool hasSecurePrefix = HasSecurePrefix(aCookieData.name());
+ bool hasHostPrefix = HasHostPrefix(aCookieData.name());
- if (!isSecure && !isHost) {
+ if (!hasSecurePrefix && !hasHostPrefix) {
// not one of the magic prefixes: carry on
return true;
}
@@ -2072,7 +2157,7 @@ bool CookieService::CheckPrefixes(CookieStruct& aCookieData,
return false;
}
- if (isHost) {
+ if (hasHostPrefix) {
// The host prefix requires that the path is "/" and that the cookie
// had no domain attribute. CheckDomain() and CheckPath() MUST be run
// first to make sure invalid attributes are rejected and to regularlize
diff --git a/netwerk/cookie/CookieService.h b/netwerk/cookie/CookieService.h
index 51344d6909..ca409cb12f 100644
--- a/netwerk/cookie/CookieService.h
+++ b/netwerk/cookie/CookieService.h
@@ -124,7 +124,6 @@ class CookieService final : public nsICookieService,
static bool CheckDomain(CookieStruct& aCookieData, nsIURI* aHostURI,
const nsACString& aBaseDomain,
bool aRequireHostMatch);
- static bool CheckHiddenPrefix(CookieStruct& aCookieData);
static bool CheckPath(CookieStruct& aCookieData,
nsIConsoleReportCollector* aCRC, nsIURI* aHostURI);
static bool CheckPrefixes(CookieStruct& aCookieData, bool aSecureRequest);
diff --git a/netwerk/cookie/CookieServiceChild.cpp b/netwerk/cookie/CookieServiceChild.cpp
index 84f34a9a37..dab62d1523 100644
--- a/netwerk/cookie/CookieServiceChild.cpp
+++ b/netwerk/cookie/CookieServiceChild.cpp
@@ -96,9 +96,9 @@ RefPtr<GenericPromise> CookieServiceChild::TrackCookieLoad(
aChannel->GetURI(getter_AddRefs(uri));
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
- OriginAttributes attrs = loadInfo->GetOriginAttributes();
+ OriginAttributes storageOriginAttributes = loadInfo->GetOriginAttributes();
StoragePrincipalHelper::PrepareEffectiveStoragePrincipalOriginAttributes(
- aChannel, attrs);
+ aChannel, storageOriginAttributes);
bool isSafeTopLevelNav = CookieCommons::IsSafeTopLevelNav(aChannel);
bool hadCrossSiteRedirects = false;
@@ -107,11 +107,30 @@ RefPtr<GenericPromise> CookieServiceChild::TrackCookieLoad(
RefPtr<CookieServiceChild> self(this);
- // TODO (Bug 1874174): A channel could access both unpartitioned and
- // partitioned cookie jars. We will need to pass partitioned and unpartitioned
- // originAttributes according the storage access.
- nsTArray<OriginAttributes> attrsList;
- attrsList.AppendElement(attrs);
+ nsTArray<OriginAttributes> originAttributesList;
+ originAttributesList.AppendElement(storageOriginAttributes);
+
+ // CHIPS - If CHIPS is enabled the partitioned cookie jar is always available
+ // (and therefore the partitioned OriginAttributes), the unpartitioned cookie
+ // jar is only available in first-party or third-party with storageAccess
+ // contexts.
+ bool isCHIPS = StaticPrefs::network_cookie_cookieBehavior_optInPartitioning();
+ bool isUnpartitioned = storageOriginAttributes.mPartitionKey.IsEmpty();
+ if (isCHIPS && isUnpartitioned) {
+ // Assert that we are only doing this if we are first-party or third-party
+ // with storageAccess.
+ MOZ_ASSERT(
+ !result.contains(ThirdPartyAnalysis::IsForeign) ||
+ result.contains(ThirdPartyAnalysis::IsStorageAccessPermissionGranted));
+ // Add the partitioned principal to principals.
+ OriginAttributes partitionedOriginAttributes;
+ StoragePrincipalHelper::GetOriginAttributes(
+ aChannel, partitionedOriginAttributes,
+ StoragePrincipalHelper::ePartitionedPrincipal);
+ originAttributesList.AppendElement(partitionedOriginAttributes);
+ // Assert partitionedOAs have partitioneKey set.
+ MOZ_ASSERT(!partitionedOriginAttributes.mPartitionKey.IsEmpty());
+ }
return SendGetCookieList(
uri, result.contains(ThirdPartyAnalysis::IsForeign),
@@ -121,7 +140,7 @@ RefPtr<GenericPromise> CookieServiceChild::TrackCookieLoad(
result.contains(
ThirdPartyAnalysis::IsStorageAccessPermissionGranted),
rejectedReason, isSafeTopLevelNav, isSameSiteForeign,
- hadCrossSiteRedirects, attrsList)
+ hadCrossSiteRedirects, originAttributesList)
->Then(
GetCurrentSerialEventTarget(), __func__,
[self, uri](const nsTArray<CookieStructTable>& aCookiesListTable) {
@@ -325,15 +344,6 @@ CookieServiceChild::GetCookieStringFromDocument(dom::Document* aDocument,
aCookieString.Truncate();
- nsCOMPtr<nsIPrincipal> cookiePrincipal =
- aDocument->EffectiveCookiePrincipal();
-
- // TODO (Bug 1874174): A document could access both unpartitioned and
- // partitioned cookie jars. We will need to prepare partitioned and
- // unpartitioned principals for access both cookie jars.
- nsTArray<nsCOMPtr<nsIPrincipal>> principals;
- principals.AppendElement(cookiePrincipal);
-
bool thirdParty = true;
nsPIDOMWindowInner* innerWindow = aDocument->GetInnerWindow();
// in gtests we don't have a window, let's consider those requests as 3rd
@@ -347,6 +357,26 @@ CookieServiceChild::GetCookieStringFromDocument(dom::Document* aDocument,
}
}
+ nsCOMPtr<nsIPrincipal> cookiePrincipal =
+ aDocument->EffectiveCookiePrincipal();
+
+ nsTArray<nsCOMPtr<nsIPrincipal>> principals;
+ principals.AppendElement(cookiePrincipal);
+
+ // CHIPS - If CHIPS is enabled the partitioned cookie jar is always available
+ // (and therefore the partitioned principal), the unpartitioned cookie jar is
+ // only available in first-party or third-party with storageAccess contexts.
+ bool isCHIPS = StaticPrefs::network_cookie_cookieBehavior_optInPartitioning();
+ bool isUnpartitioned =
+ cookiePrincipal->OriginAttributesRef().mPartitionKey.IsEmpty();
+ if (isCHIPS && isUnpartitioned) {
+ // Assert that we are only doing this if we are first-party or third-party
+ // with storageAccess.
+ MOZ_ASSERT(!thirdParty || aDocument->UsingStorageAccess());
+ // Add the partitioned principal to principals
+ principals.AppendElement(aDocument->PartitionedPrincipal());
+ }
+
for (auto& principal : principals) {
if (!CookieCommons::IsSchemeSupported(principal)) {
return NS_OK;
@@ -488,7 +518,14 @@ CookieServiceChild::SetCookieStringFromDocument(
// (those come from the parent, which already checks this),
// but script could see an inconsistent view of things.
- nsCOMPtr<nsIPrincipal> principal = aDocument->EffectiveCookiePrincipal();
+ // CHIPS - If the cookie has the "Partitioned" attribute set it will be
+ // stored in the partitioned cookie jar.
+ bool needPartitioned =
+ StaticPrefs::network_cookie_cookieBehavior_optInPartitioning() &&
+ cookie->RawIsPartitioned();
+ nsCOMPtr<nsIPrincipal> principal =
+ needPartitioned ? aDocument->PartitionedPrincipal()
+ : aDocument->EffectiveCookiePrincipal();
bool isPotentiallyTrustworthy =
principal->GetIsOriginPotentiallyTrustworthy();
@@ -560,9 +597,10 @@ CookieServiceChild::SetCookieStringFromHttp(nsIURI* aHostURI,
nsCString cookieString(aCookieString);
- OriginAttributes attrs = loadInfo->GetOriginAttributes();
+ OriginAttributes storagePrincipalOriginAttributes =
+ loadInfo->GetOriginAttributes();
StoragePrincipalHelper::PrepareEffectiveStoragePrincipalOriginAttributes(
- aChannel, attrs);
+ aChannel, storagePrincipalOriginAttributes);
bool requireHostMatch;
nsCString baseDomain;
@@ -580,18 +618,15 @@ CookieServiceChild::SetCookieStringFromHttp(nsIURI* aHostURI,
result.contains(ThirdPartyAnalysis::IsThirdPartyTrackingResource),
result.contains(ThirdPartyAnalysis::IsThirdPartySocialTrackingResource),
result.contains(ThirdPartyAnalysis::IsStorageAccessPermissionGranted),
- aCookieString, CountCookiesFromHashTable(baseDomain, attrs), attrs,
- &rejectedReason);
+ aCookieString,
+ CountCookiesFromHashTable(baseDomain, storagePrincipalOriginAttributes),
+ storagePrincipalOriginAttributes, &rejectedReason);
if (cookieStatus != STATUS_ACCEPTED &&
cookieStatus != STATUS_ACCEPT_SESSION) {
return NS_OK;
}
- CookieKey key(baseDomain, attrs);
-
- nsTArray<CookieStruct> cookiesToSend;
-
int64_t currentTimeInUsec = PR_Now();
bool addonAllowsLoad = false;
@@ -612,6 +647,23 @@ CookieServiceChild::SetCookieStringFromHttp(nsIURI* aHostURI,
nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN &&
!result.contains(ThirdPartyAnalysis::IsStorageAccessPermissionGranted);
+ // CHIPS - The partitioned cookie jar is always available and it is always
+ // possible to store cookies in it using the "Partitioned" attribute.
+ // Prepare the partitioned principals OAs to enable possible partitioned
+ // cookie storing from first-party or with StorageAccess.
+ // Similar behavior to CookieService::SetCookieStringFromHttp().
+ OriginAttributes partitionedPrincipalOriginAttributes;
+ bool isPartitionedPrincipal =
+ !storagePrincipalOriginAttributes.mPartitionKey.IsEmpty();
+ bool isCHIPS = StaticPrefs::network_cookie_cookieBehavior_optInPartitioning();
+ // Only need to get OAs if we don't already use the partitioned principal.
+ if (isCHIPS && !isPartitionedPrincipal) {
+ StoragePrincipalHelper::GetOriginAttributes(
+ aChannel, partitionedPrincipalOriginAttributes,
+ StoragePrincipalHelper::ePartitionedPrincipal);
+ }
+
+ nsTArray<CookieStruct> cookiesToSend, partitionedCookiesToSend;
bool moreCookies;
do {
CookieStruct cookieData;
@@ -642,23 +694,47 @@ CookieServiceChild::SetCookieStringFromHttp(nsIURI* aHostURI,
continue;
}
- RefPtr<Cookie> cookie = Cookie::Create(cookieData, attrs);
+ // CHIPS - If the partitioned attribute is set, store cookie in partitioned
+ // cookie jar independent of context. If the cookies are stored in the
+ // partitioned cookie jar anyway no special treatment of CHIPS cookies
+ // necessary.
+ bool needPartitioned =
+ isCHIPS && cookieData.isPartitioned() && !isPartitionedPrincipal;
+ nsTArray<CookieStruct>& cookiesToSendRef =
+ needPartitioned ? partitionedCookiesToSend : cookiesToSend;
+ OriginAttributes& cookieOriginAttributes =
+ needPartitioned ? partitionedPrincipalOriginAttributes
+ : storagePrincipalOriginAttributes;
+ // Assert that partitionedPrincipalOriginAttributes are initialized if used.
+ MOZ_ASSERT_IF(
+ needPartitioned,
+ !partitionedPrincipalOriginAttributes.mPartitionKey.IsEmpty());
+
+ RefPtr<Cookie> cookie = Cookie::Create(cookieData, cookieOriginAttributes);
MOZ_ASSERT(cookie);
cookie->SetLastAccessed(currentTimeInUsec);
cookie->SetCreationTime(
Cookie::GenerateUniqueCreationTime(currentTimeInUsec));
- RecordDocumentCookie(cookie, attrs);
- cookiesToSend.AppendElement(cookieData);
+ RecordDocumentCookie(cookie, cookieOriginAttributes);
+ cookiesToSendRef.AppendElement(cookieData);
} while (moreCookies);
// Asynchronously call the parent.
- if (CanSend() && !cookiesToSend.IsEmpty()) {
+ if (CanSend()) {
RefPtr<HttpChannelChild> httpChannelChild = do_QueryObject(aChannel);
MOZ_ASSERT(httpChannelChild);
- httpChannelChild->SendSetCookies(baseDomain, attrs, aHostURI, true,
- cookiesToSend);
+ if (!cookiesToSend.IsEmpty()) {
+ httpChannelChild->SendSetCookies(baseDomain,
+ storagePrincipalOriginAttributes,
+ aHostURI, true, cookiesToSend);
+ }
+ if (!partitionedCookiesToSend.IsEmpty()) {
+ httpChannelChild->SendSetCookies(
+ baseDomain, partitionedPrincipalOriginAttributes, aHostURI, true,
+ partitionedCookiesToSend);
+ }
}
return NS_OK;
diff --git a/netwerk/cookie/CookieServiceParent.cpp b/netwerk/cookie/CookieServiceParent.cpp
index 75c024cec6..187a31e002 100644
--- a/netwerk/cookie/CookieServiceParent.cpp
+++ b/netwerk/cookie/CookieServiceParent.cpp
@@ -15,6 +15,7 @@
#include "mozIThirdPartyUtil.h"
#include "nsArrayUtils.h"
#include "nsIChannel.h"
+#include "mozilla/StaticPrefs_network.h"
#include "nsIEffectiveTLDService.h"
#include "nsNetCID.h"
#include "nsMixedContentBlocker.h"
@@ -119,17 +120,11 @@ void CookieServiceParent::TrackCookieLoad(nsIChannel* aChannel) {
aChannel->GetURI(getter_AddRefs(uri));
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
- OriginAttributes attrs = loadInfo->GetOriginAttributes();
bool isSafeTopLevelNav = CookieCommons::IsSafeTopLevelNav(aChannel);
bool hadCrossSiteRedirects = false;
bool isSameSiteForeign =
CookieCommons::IsSameSiteForeign(aChannel, uri, &hadCrossSiteRedirects);
- // TODO (Bug 1874174): A channel could load both unpartitioned and partitioned
- // cookie jars together. We will need to track both originAttributes for them.
- StoragePrincipalHelper::PrepareEffectiveStoragePrincipalOriginAttributes(
- aChannel, attrs);
-
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil;
thirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID);
@@ -137,8 +132,34 @@ void CookieServiceParent::TrackCookieLoad(nsIChannel* aChannel) {
ThirdPartyAnalysisResult result = thirdPartyUtil->AnalyzeChannel(
aChannel, false, nullptr, nullptr, &rejectedReason);
+ OriginAttributes storageOriginAttributes = loadInfo->GetOriginAttributes();
+ StoragePrincipalHelper::PrepareEffectiveStoragePrincipalOriginAttributes(
+ aChannel, storageOriginAttributes);
+
nsTArray<OriginAttributes> originAttributesList;
- originAttributesList.AppendElement(attrs);
+ originAttributesList.AppendElement(storageOriginAttributes);
+
+ // CHIPS - If CHIPS is enabled the partitioned cookie jar is always available
+ // (and therefore the partitioned OriginAttributes), the unpartitioned cookie
+ // jar is only available in first-party or third-party with storageAccess
+ // contexts.
+ bool isCHIPS = StaticPrefs::network_cookie_cookieBehavior_optInPartitioning();
+ bool isUnpartitioned = storageOriginAttributes.mPartitionKey.IsEmpty();
+ if (isCHIPS && isUnpartitioned) {
+ // Assert that we are only doing this if we are first-party or third-party
+ // with storageAccess.
+ MOZ_ASSERT(
+ !result.contains(ThirdPartyAnalysis::IsForeign) ||
+ result.contains(ThirdPartyAnalysis::IsStorageAccessPermissionGranted));
+ // Add the partitioned principal to principals
+ OriginAttributes partitionedOriginAttributes;
+ StoragePrincipalHelper::GetOriginAttributes(
+ aChannel, partitionedOriginAttributes,
+ StoragePrincipalHelper::ePartitionedPrincipal);
+ originAttributesList.AppendElement(partitionedOriginAttributes);
+ // Assert partitionedOAs have partitioneKey set.
+ MOZ_ASSERT(!partitionedOriginAttributes.mPartitionKey.IsEmpty());
+ }
for (auto& originAttributes : originAttributesList) {
UpdateCookieInContentList(uri, originAttributes);
diff --git a/netwerk/cookie/test/browser/browser.toml b/netwerk/cookie/test/browser/browser.toml
index 05a302ddbd..56807e4bf1 100644
--- a/netwerk/cookie/test/browser/browser.toml
+++ b/netwerk/cookie/test/browser/browser.toml
@@ -8,6 +8,9 @@ support-files = [
["browser_broadcastChannel.js"]
+["browser_cookie_chips.js"]
+support-files = ["chips.sjs"]
+
["browser_cookie_insecure_overwrites_secure.js"]
["browser_cookie_purge_sync.js"]
@@ -17,6 +20,9 @@ support-files = ["server.sjs"]
["browser_cookies_ipv6.js"]
+["browser_cookies_serviceWorker.js"]
+support-files = ["cookies.sjs", "serviceWorker.js"]
+
["browser_domCache.js"]
["browser_indexedDB.js"]
diff --git a/netwerk/cookie/test/browser/browser_cookie_chips.js b/netwerk/cookie/test/browser/browser_cookie_chips.js
new file mode 100644
index 0000000000..ba0c8f3a0e
--- /dev/null
+++ b/netwerk/cookie/test/browser/browser_cookie_chips.js
@@ -0,0 +1,539 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_setup(() => {
+ // These are functional and not integration tests, cookieBehavior accept lets
+ // us have StorageAccess on thirparty.
+ Services.prefs.setIntPref(
+ "network.cookie.cookieBehavior",
+ Ci.nsICookieService.BEHAVIOR_ACCEPT
+ );
+ Services.prefs.setBoolPref(
+ "network.cookieJarSettings.unblocked_for_testing",
+ true
+ );
+ Services.prefs.setBoolPref(
+ "network.cookie.cookieBehavior.optInPartitioning",
+ true
+ );
+ Services.prefs.setBoolPref("dom.storage_access.enabled", true);
+ Services.prefs.setBoolPref("dom.storage_access.prompt.testing", true);
+ Services.cookies.removeAll();
+ Services.perms.removeAll();
+});
+
+registerCleanupFunction(() => {
+ Services.prefs.clearUserPref("network.cookie.cookieBehavior");
+ Services.prefs.clearUserPref(
+ "network.cookieJarSettings.unblocked_for_testing"
+ );
+ Services.prefs.clearUserPref(
+ "network.cookie.cookieBehavior.optInPartitioning"
+ );
+ Services.prefs.clearUserPref("dom.storage_access.enabled");
+ Services.prefs.clearUserPref("dom.storage_access.prompt.testing");
+ Services.cookies.removeAll();
+ Services.perms.removeAll();
+});
+
+const COOKIE_PARTITIONED =
+ "cookie=partitioned; Partitioned; Secure; SameSite=None;";
+const COOKIE_UNPARTITIONED = "cookie=unpartitioned; Secure; SameSite=None;";
+
+const PATH = "/browser/netwerk/cookie/test/browser/";
+const PATH_EMPTY = PATH + "file_empty.html";
+const HTTP_COOKIE_SET = PATH + "chips.sjs?set";
+const HTTP_COOKIE_GET = PATH + "chips.sjs?get";
+
+const FIRST_PARTY = "example.com";
+const THIRD_PARTY = "example.org";
+
+const URL_DOCUMENT_FIRSTPARTY = "https://" + FIRST_PARTY + PATH_EMPTY;
+const URL_DOCUMENT_THIRDPARTY = "https://" + THIRD_PARTY + PATH_EMPTY;
+const URL_HTTP_FIRSTPARTY = "https://" + FIRST_PARTY + "/" + HTTP_COOKIE_SET;
+const URL_HTTP_THIRDPARTY = "https://" + THIRD_PARTY + "/" + HTTP_COOKIE_SET;
+
+function createOriginAttributes(partitionKey) {
+ return JSON.stringify({
+ firstPartyDomain: "",
+ geckoViewSessionContextId: "",
+ inIsolatedMozBrowser: false,
+ partitionKey,
+ privateBrowsingId: 0,
+ userContextId: 0,
+ });
+}
+
+function createPartitonKey(url) {
+ let uri = NetUtil.newURI(url);
+ return `(${uri.scheme},${uri.host})`;
+}
+
+// OriginAttributes used to access partitioned and unpartitioned cookie jars
+// in all tests.
+const partitionedOAs = createOriginAttributes(
+ createPartitonKey(URL_DOCUMENT_FIRSTPARTY)
+);
+const unpartitionedOAs = createOriginAttributes("");
+
+// Set partitioned and unpartitioned cookie from first-party document.
+// CHIPS "Partitioned" cookie MUST always be stored in partitioned jar.
+// This calls CookieServiceChild::SetCookieStringFromDocument() internally.
+// CookieService::SetCookieStringFromDocument() is not explicitly tested since
+// CHIPS are in the common function CookieCommons::CreateCookieFromDocument().
+add_task(
+ async function test_chips_store_partitioned_document_first_party_child() {
+ const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
+ const browser = gBrowser.getBrowserForTab(tab);
+ await BrowserTestUtils.browserLoaded(browser);
+
+ // Set partitioned and unpartitioned cookie from document child-side
+ await SpecialPowers.spawn(
+ browser,
+ [COOKIE_PARTITIONED, COOKIE_UNPARTITIONED],
+ (partitioned, unpartitioned) => {
+ content.document.cookie = partitioned;
+ content.document.cookie = unpartitioned;
+ }
+ );
+
+ // Get cookies from partitioned jar
+ let partitioned = Services.cookies.getCookiesWithOriginAttributes(
+ partitionedOAs,
+ FIRST_PARTY
+ );
+ // Get cookies from unpartitioned jar
+ let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
+ unpartitionedOAs,
+ FIRST_PARTY
+ );
+
+ // Assert partitioned/unpartitioned cookie were stored in correct jars
+ Assert.equal(partitioned.length, 1);
+ Assert.equal(partitioned[0].value, "partitioned");
+ Assert.equal(unpartitioned.length, 1);
+ Assert.equal(unpartitioned[0].value, "unpartitioned");
+
+ // Cleanup
+ BrowserTestUtils.removeTab(tab);
+ Services.cookies.removeAll();
+ }
+);
+
+// Set partitioned and unpartitioned cookie from third-party document with storage
+// access. CHIPS "Partitioned" cookie MUST always be stored in partitioned jar.
+// This calls CookieServiceChild::SetCookieStringFromDocument() internally.
+// CookieService::SetCookieStringFromDocument() is not explicitly tested since
+// CHIPS are in the common function CookieCommons::CreateCookieFromDocument().
+add_task(
+ async function test_chips_store_partitioned_document_third_party_storage_access_child() {
+ const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
+ const browser = gBrowser.getBrowserForTab(tab);
+ await BrowserTestUtils.browserLoaded(browser);
+
+ // Spawn document bc
+ await SpecialPowers.spawn(
+ browser,
+ [URL_DOCUMENT_THIRDPARTY, COOKIE_PARTITIONED, COOKIE_UNPARTITIONED],
+ async (url, partitioned, unpartitioned) => {
+ let ifr = content.document.createElement("iframe");
+ ifr.src = url;
+ content.document.body.appendChild(ifr);
+ await ContentTaskUtils.waitForEvent(ifr, "load");
+
+ // Spawn iframe bc
+ await SpecialPowers.spawn(
+ await ifr.browsingContext,
+ [partitioned, unpartitioned],
+ async (partitioned, unpartitioned) => {
+ ok(
+ await content.document.hasStorageAccess(),
+ "example.org should have storageAccess by CookieBehavior 0 / test setup"
+ );
+
+ content.document.cookie = partitioned;
+ content.document.cookie = unpartitioned;
+ }
+ );
+ }
+ );
+
+ // Get cookies from partitioned jar
+ let partitioned = Services.cookies.getCookiesWithOriginAttributes(
+ partitionedOAs,
+ THIRD_PARTY
+ );
+ // Get cookies from unpartitioned jar
+ let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
+ unpartitionedOAs,
+ THIRD_PARTY
+ );
+
+ // Assert partitioned/unpartitioned cookie were stored in correct jars
+ Assert.equal(partitioned.length, 1);
+ Assert.equal(partitioned[0].value, "partitioned");
+ Assert.equal(unpartitioned.length, 1);
+ Assert.equal(unpartitioned[0].value, "unpartitioned");
+
+ // Cleanup
+ BrowserTestUtils.removeTab(tab);
+ Services.cookies.removeAll();
+ }
+);
+
+// Set partitioned and unpartitioned cookie from first-party http load.
+// CHIPS "Partitioned" cookie MUST always be stored in partitioned jar.
+// This calls CookieService::SetCookieStringFromHttp() internally.
+add_task(async function test_chips_store_partitioned_http_first_party_parent() {
+ // Set partitioned and unpartitioned cookie from http parent side through
+ // chips.sjs being loaded.
+ const tab = BrowserTestUtils.addTab(gBrowser, URL_HTTP_FIRSTPARTY);
+ const browser = gBrowser.getBrowserForTab(tab);
+ await BrowserTestUtils.browserLoaded(browser);
+
+ // Get cookies from partitioned jar
+ let partitioned = Services.cookies.getCookiesWithOriginAttributes(
+ partitionedOAs,
+ FIRST_PARTY
+ );
+ // Get cookies from unpartitioned jar
+ let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
+ unpartitionedOAs,
+ FIRST_PARTY
+ );
+
+ // Assert partitioned/unpartitioned cookie were stored in correct jars
+ Assert.equal(partitioned.length, 1);
+ Assert.equal(partitioned[0].value, "partitioned");
+ Assert.equal(unpartitioned.length, 1);
+ Assert.equal(unpartitioned[0].value, "unpartitioned");
+
+ // Cleanup
+ BrowserTestUtils.removeTab(tab);
+ Services.cookies.removeAll();
+});
+
+// Set partitioned and unpartitioned cookie from third-party http load.
+// CHIPS "Partitioned" cookie MUST always be stored in partitioned jar.
+// This calls CookieService::SetCookieStringFromHttp() internally.
+add_task(
+ async function test_chips_store_partitioned_http_third_party_storage_access_parent() {
+ const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
+ const browser = gBrowser.getBrowserForTab(tab);
+ await BrowserTestUtils.browserLoaded(browser);
+
+ // Spawn document bc
+ await SpecialPowers.spawn(browser, [URL_HTTP_THIRDPARTY], async url => {
+ let ifr = content.document.createElement("iframe");
+ ifr.src = url;
+ content.document.body.appendChild(ifr);
+ // Send http request with "set" query parameter, partitioned and
+ // unpartitioned cookie will be set through http response from chips.sjs.
+ await ContentTaskUtils.waitForEvent(ifr, "load");
+
+ // Spawn iframe bc
+ await SpecialPowers.spawn(await ifr.browsingContext, [], async () => {
+ ok(
+ await content.document.hasStorageAccess(),
+ "example.org should have storageAccess by CookieBehavior 0 / test setup"
+ );
+ });
+ });
+
+ // Get cookies from partitioned jar
+ let partitioned = Services.cookies.getCookiesWithOriginAttributes(
+ partitionedOAs,
+ THIRD_PARTY
+ );
+ // Get cookies from unpartitioned jar
+ let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
+ unpartitionedOAs,
+ THIRD_PARTY
+ );
+
+ // Assert partitioned/unpartitioned cookie were stored in correct jars
+ Assert.equal(partitioned.length, 1);
+ Assert.equal(partitioned[0].value, "partitioned");
+ Assert.equal(unpartitioned.length, 1);
+ Assert.equal(unpartitioned[0].value, "unpartitioned");
+
+ // Cleanup
+ BrowserTestUtils.removeTab(tab);
+ Services.cookies.removeAll();
+ }
+);
+
+// TODO CHIPS - Tests for CookieServiceChild::SetCookieStringFromHttp() need
+// to be added. Since this is only checkable on onProxyConnectSuccess needs
+// proxy setup test harness. It is also called after onStartRequest() (Http)
+// but cookies are already set by the parents
+// CookieService::SetCookieStringFromHttp() call.
+
+// Get partitioned and unpartitioned cookies from document (child).
+// This calls CookieServiceChild::GetCookieStringFromDocument() internally.
+add_task(
+ async function test_chips_send_partitioned_and_unpartitioned_document_child() {
+ const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
+ const browser = gBrowser.getBrowserForTab(tab);
+ await BrowserTestUtils.browserLoaded(browser);
+
+ // Spawn document bc
+ await SpecialPowers.spawn(
+ browser,
+ [COOKIE_PARTITIONED, COOKIE_UNPARTITIONED],
+ async (partitioned, unpartitioned) => {
+ content.document.cookie = partitioned;
+ content.document.cookie = unpartitioned;
+
+ // Assert both unpartitioned and partitioned cookie are returned.
+ let cookies = content.document.cookie;
+ ok(
+ cookies.includes("cookie=partitioned"),
+ "Cookie from partitioned jar was sent."
+ );
+ ok(
+ cookies.includes("cookie=unpartitioned"),
+ "Cookie from unpartitioned jar was sent."
+ );
+ }
+ );
+
+ // Cleanup
+ BrowserTestUtils.removeTab(tab);
+ Services.cookies.removeAll();
+ }
+);
+
+// Get partitioned and unpartitioned cookies from document (child) after
+// storageAccess was granted. This calls CookieServiceChild::TrackCookieLoad()
+// internally to update child's cookies.
+add_task(
+ async function test_chips_send_partitioned_and_unpartitioned_on_storage_access_child() {
+ // Set cookieBehavior to BEHAVIOR_REJECT_TRACKERS_AND_PARTITION_FOREIGN for
+ // requestStorageAccess() based test.
+ Services.prefs.setIntPref("network.cookie.cookieBehavior", 5);
+
+ // Set example.org first-party unpartitioned cookie
+ await BrowserTestUtils.withNewTab(
+ URL_DOCUMENT_THIRDPARTY,
+ async browser => {
+ info("Set a first party cookie via `document.cookie`.");
+ await SpecialPowers.spawn(
+ browser,
+ [COOKIE_UNPARTITIONED],
+ async unpartitioned => {
+ content.document.cookie = unpartitioned;
+ is(
+ content.document.cookie,
+ "cookie=unpartitioned",
+ "Unpartitioned cookie was set."
+ );
+ }
+ );
+ }
+ );
+
+ // Assert cookie was set on parent cookie service for example.org.
+ // Get cookies from unpartitioned jar
+ let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
+ unpartitionedOAs,
+ THIRD_PARTY
+ );
+ Assert.equal(unpartitioned.length, 1);
+ Assert.equal(unpartitioned[0].value, "unpartitioned");
+
+ // Load example.com as first-party in tab
+ const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
+ const browser = gBrowser.getBrowserForTab(tab);
+ await BrowserTestUtils.browserLoaded(browser);
+
+ // Set third-party cookie from example.org iframe, get storageAccess and
+ // check cookies.
+ // Spawn document bc
+ await SpecialPowers.spawn(
+ browser,
+ [URL_DOCUMENT_THIRDPARTY, COOKIE_PARTITIONED],
+ async (url, partitioned) => {
+ // Create third-party iframe
+ let ifr = content.document.createElement("iframe");
+ ifr.src = url;
+ content.document.body.appendChild(ifr);
+ await ContentTaskUtils.waitForEvent(ifr, "load");
+
+ // Spawn iframe bc
+ await SpecialPowers.spawn(
+ await ifr.browsingContext,
+ [partitioned],
+ async partitioned => {
+ ok(
+ !(await content.document.hasStorageAccess()),
+ "example.org should not have storageAccess initially."
+ );
+
+ // Set a partitioned third-party cookie and assert its the only.
+ content.document.cookie = partitioned;
+ is(
+ content.document.cookie,
+ "cookie=partitioned",
+ "Partitioned cookie was set."
+ );
+
+ info("Simulate user activation.");
+ SpecialPowers.wrap(content.document).notifyUserGestureActivation();
+
+ info("Request storage access.");
+ await content.document.requestStorageAccess();
+
+ ok(
+ await content.document.hasStorageAccess(),
+ "example.org should now have storageAccess."
+ );
+
+ // Assert both unpartitioned and partitioned cookie are returned.
+ let cookies = content.document.cookie;
+ ok(
+ cookies.includes("cookie=partitioned"),
+ "Cookie from partitioned jar was sent."
+ );
+ ok(
+ cookies.includes("cookie=unpartitioned"),
+ "Cookie from unpartitioned jar was sent."
+ );
+ }
+ );
+ }
+ );
+
+ // Cleanup
+ BrowserTestUtils.removeTab(tab);
+ Services.cookies.removeAll();
+ Services.perms.removeAll();
+ Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+ }
+);
+
+// Set partitioned and unpartitioned cookies for URL_DOCUMENT_FIRSTPARTY, then
+// load URL again, assure cookies are correctly send to content child process.
+// This tests CookieServiceParent::TrackCookieLoad() internally.
+add_task(
+ async function test_chips_send_partitioned_and_unpartitioned_document_parent() {
+ // Set example.com first-party unpartitioned and partitioned cookie, then
+ // close tab.
+ await BrowserTestUtils.withNewTab(
+ URL_DOCUMENT_FIRSTPARTY,
+ async browser => {
+ await SpecialPowers.spawn(
+ browser,
+ [COOKIE_PARTITIONED, COOKIE_UNPARTITIONED],
+ async (partitioned, unpartitioned) => {
+ content.document.cookie = unpartitioned;
+ content.document.cookie = partitioned;
+ let cookies = content.document.cookie;
+ ok(
+ cookies.includes("cookie=unpartitioned"),
+ "Unpartitioned cookie was set."
+ );
+ ok(
+ cookies.includes("cookie=partitioned"),
+ "Partitioned cookie was set."
+ );
+ }
+ );
+ }
+ );
+
+ // Assert we have one partitioned and one unpartitioned cookie set.
+ // Get cookies from partitioned jar
+ let partitioned = Services.cookies.getCookiesWithOriginAttributes(
+ partitionedOAs,
+ FIRST_PARTY
+ );
+ // Get cookies from unpartitioned jar
+ let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
+ unpartitionedOAs,
+ FIRST_PARTY
+ );
+ Assert.equal(partitioned.length, 1);
+ Assert.equal(partitioned[0].value, "partitioned");
+ Assert.equal(unpartitioned.length, 1);
+ Assert.equal(unpartitioned[0].value, "unpartitioned");
+
+ // Reload example.com and assert previously set cookies are correctly
+ // send to content child document.
+ await BrowserTestUtils.withNewTab(
+ URL_DOCUMENT_FIRSTPARTY,
+ async browser => {
+ await SpecialPowers.spawn(browser, [], () => {
+ let cookies = content.document.cookie;
+ ok(
+ cookies.includes("cookie=unpartitioned"),
+ "Unpartitioned cookie was sent."
+ );
+ ok(
+ cookies.includes("cookie=partitioned"),
+ "Partitioned cookie was sent."
+ );
+ });
+ }
+ );
+
+ // Cleanup
+ Services.cookies.removeAll();
+ }
+);
+
+// Set partitioned and unpartitioned cookies for URL_DOCUMENT_FIRSTPARTY, then
+// send http request, assure cookies are correctly send in "Cookie" header.
+// This tests CookieService::GetCookieStringFromHttp() internally.
+add_task(
+ async function test_chips_send_partitioned_and_unpartitioned_http_parent() {
+ // Load empty document.
+ let tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
+ let browser = gBrowser.getBrowserForTab(tab);
+ await BrowserTestUtils.browserLoaded(browser);
+
+ await SpecialPowers.spawn(
+ browser,
+ [HTTP_COOKIE_SET, HTTP_COOKIE_GET],
+ async (set, get) => {
+ // Send http request with "set" query parameter, partitioned and
+ // unpartitioned cookie will be set through http response.
+ await content.fetch(set);
+
+ // Assert cookies were set to document.
+ let cookies = content.document.cookie;
+ ok(
+ cookies.includes("cookie=unpartitioned"),
+ "Unpartitioned cookie was set to document."
+ );
+ ok(
+ cookies.includes("cookie=partitioned"),
+ "Partitioned cookie was set to document."
+ );
+
+ // Send http request with "get" query parameter, chips.sjs will return
+ // the request "Cookie" header string.
+ await content
+ .fetch(get)
+ .then(response => response.text())
+ .then(requestCookies => {
+ // Assert cookies were sent in http request.
+ ok(
+ requestCookies.includes("cookie=unpartitioned"),
+ "Unpartitioned cookie was sent in http request."
+ );
+ ok(
+ requestCookies.includes("cookie=partitioned"),
+ "Partitioned cookie was sent in http request."
+ );
+ });
+ }
+ );
+
+ // Cleanup
+ BrowserTestUtils.removeTab(tab);
+ Services.cookies.removeAll();
+ }
+);
diff --git a/netwerk/cookie/test/browser/browser_cookies_serviceWorker.js b/netwerk/cookie/test/browser/browser_cookies_serviceWorker.js
new file mode 100644
index 0000000000..813e1fe7cb
--- /dev/null
+++ b/netwerk/cookie/test/browser/browser_cookies_serviceWorker.js
@@ -0,0 +1,540 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TEST_CROSS_SITE_DOMAIN = "https://example.net/";
+const TEST_CROSS_SITE_PAGE =
+ TEST_CROSS_SITE_DOMAIN + TEST_PATH + "file_empty.html";
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["dom.serviceWorkers.enabled", true],
+ ["dom.serviceWorkers.testing.enabled", true],
+ ],
+ });
+
+ Services.cookies.removeAll();
+});
+
+function registerSW(browser) {
+ return SpecialPowers.spawn(browser, [], async _ => {
+ let reg = await content.navigator.serviceWorker.register(
+ "serviceWorker.js"
+ );
+
+ await ContentTaskUtils.waitForCondition(() => {
+ return reg.active && reg.active.state === "activated";
+ }, "The service worker is activated");
+
+ ok(
+ content.navigator.serviceWorker.controller,
+ "The service worker controls the document successfully."
+ );
+ });
+}
+
+function fetchCookiesFromSW(browser) {
+ return SpecialPowers.spawn(browser, [], async _ => {
+ return new content.Promise(resolve => {
+ content.navigator.serviceWorker.addEventListener("message", event => {
+ resolve(event.data.content);
+ });
+
+ content.navigator.serviceWorker.controller.postMessage({
+ action: "fetch",
+ url: `cookies.sjs`,
+ });
+ });
+ });
+}
+
+function setCookiesFromSW(browser, cookies) {
+ let setCookieQuery = "";
+
+ for (let cookie of cookies) {
+ setCookieQuery += `Set-Cookie=${cookie}&`;
+ }
+
+ return SpecialPowers.spawn(browser, [setCookieQuery], async query => {
+ return new content.Promise(resolve => {
+ content.navigator.serviceWorker.addEventListener("message", event => {
+ resolve(event.data.content);
+ });
+
+ content.navigator.serviceWorker.controller.postMessage({
+ action: "fetch",
+ url: `cookies.sjs?${query}`,
+ });
+ });
+ });
+}
+
+function unregisterSW(browser) {
+ return SpecialPowers.spawn(browser, [], async _ => {
+ const regs = await content.navigator.serviceWorker.getRegistrations();
+ for (const reg of regs) {
+ await reg.unregister();
+ }
+ });
+}
+
+/**
+ * Verify a first-party service worker can access both SameSite=None and
+ * SameSite=Lax cookies set in the first-party context.
+ */
+add_task(async function testCookiesWithFirstPartyServiceWorker() {
+ info("Open a tab");
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ TEST_TOP_PAGE
+ );
+
+ info("Writing cookies to the first-party context.");
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async _ => {
+ const cookies = [
+ "foo=bar; SameSite=None; Secure",
+ "fooLax=barLax; SameSite=Lax; Secure",
+ ];
+
+ let query = "";
+
+ for (let cookie of cookies) {
+ query += `Set-Cookie=${cookie}&`;
+ }
+
+ await content.fetch(`cookies.sjs?${query}`);
+ });
+
+ info("Register a service worker and trigger a fetch request to get cookies.");
+ await registerSW(tab.linkedBrowser);
+ let cookieStr = await fetchCookiesFromSW(tab.linkedBrowser);
+
+ is(cookieStr, "foo=bar; fooLax=barLax", "The cookies are expected");
+
+ info("Set cookies from the service worker.");
+ await setCookiesFromSW(tab.linkedBrowser, [
+ "foo=barSW; SameSite=None; Secure",
+ "fooLax=barLaxSW; SameSite=Lax; Secure",
+ ]);
+
+ info("Get cookies from the service worker.");
+ cookieStr = await fetchCookiesFromSW(tab.linkedBrowser);
+
+ is(cookieStr, "foo=barSW; fooLax=barLaxSW", "The cookies are expected");
+
+ await unregisterSW(tab.linkedBrowser);
+ BrowserTestUtils.removeTab(tab);
+ Services.cookies.removeAll();
+});
+
+/**
+ * Verify a cross-site service worker can only access cookies set in the
+ * same cross-site context.
+ */
+add_task(async function testCookiesWithCrossSiteServiceWorker() {
+ // Disable blocking third-party cookies.
+ await SpecialPowers.pushPrefEnv({
+ set: [["network.cookie.cookieBehavior.optInPartitioning", false]],
+ });
+
+ info("Open a cross-site tab");
+ let crossSiteTab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ TEST_CROSS_SITE_PAGE
+ );
+
+ info("Writing cookies to the cross site in the first-party context.");
+ await SpecialPowers.spawn(crossSiteTab.linkedBrowser, [], async _ => {
+ const cookies = [
+ "foo=bar; SameSite=None; Secure",
+ "fooLax=barLax; SameSite=Lax; Secure",
+ ];
+
+ let query = "";
+
+ for (let cookie of cookies) {
+ query += `Set-Cookie=${cookie}&`;
+ }
+
+ await content.fetch(`cookies.sjs?${query}`);
+ });
+
+ info("Open a tab");
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ TEST_TOP_PAGE
+ );
+
+ info("Load a cross-site iframe");
+ let crossSiteBc = await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [TEST_CROSS_SITE_PAGE],
+ async url => {
+ let ifr = content.document.createElement("iframe");
+
+ await new content.Promise(resolve => {
+ ifr.onload = resolve;
+ content.document.body.appendChild(ifr);
+ ifr.src = url;
+ });
+
+ return ifr.browsingContext;
+ }
+ );
+
+ info("Write cookies in the cross-site iframe");
+ await SpecialPowers.spawn(crossSiteBc, [], async _ => {
+ const cookies = [
+ "foo=crossBar; SameSite=None; Secure",
+ "fooLax=crossBarLax; SameSite=Lax; Secure",
+ ];
+
+ let query = "";
+
+ for (let cookie of cookies) {
+ query += `Set-Cookie=${cookie}&`;
+ }
+
+ await content.fetch(`cookies.sjs?${query}`);
+ });
+
+ info(
+ "Register a service worker and trigger a fetch request to get cookies in cross-site context."
+ );
+ await registerSW(crossSiteBc);
+ let cookieStr = await fetchCookiesFromSW(crossSiteBc);
+
+ is(
+ cookieStr,
+ "foo=crossBar",
+ "Only the SameSite=None cookie set in the third-party iframe is available."
+ );
+
+ info("Set cookies from the third-party service worker.");
+ await setCookiesFromSW(crossSiteBc, [
+ "foo=crossBarSW; SameSite=None; Secure",
+ "fooLax=crossBarLaxSW; SameSite=Lax; Secure",
+ ]);
+
+ info("Get cookies from the third-party service worker.");
+ cookieStr = await fetchCookiesFromSW(crossSiteBc);
+
+ is(
+ cookieStr,
+ "foo=crossBarSW",
+ "Only the SameSite=None cookie set in the third-party service worker is available."
+ );
+
+ await unregisterSW(crossSiteBc);
+ BrowserTestUtils.removeTab(crossSiteTab);
+ BrowserTestUtils.removeTab(tab);
+ Services.cookies.removeAll();
+});
+
+/**
+ * Verify a cross-site service worker can only access partitioned cookies set in
+ * the same cross-site context if third-party cookies are blocked.
+ */
+add_task(async function testPartitionedCookiesWithCrossSiteServiceWorker() {
+ // Enable blocking third-party cookies.
+ await SpecialPowers.pushPrefEnv({
+ set: [["network.cookie.cookieBehavior.optInPartitioning", true]],
+ });
+
+ info("Open a tab");
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ TEST_TOP_PAGE
+ );
+
+ info("Load a cross-site iframe");
+ let crossSiteBc = await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [TEST_CROSS_SITE_PAGE],
+ async url => {
+ let ifr = content.document.createElement("iframe");
+
+ await new content.Promise(resolve => {
+ ifr.onload = resolve;
+ content.document.body.appendChild(ifr);
+ ifr.src = url;
+ });
+
+ return ifr.browsingContext;
+ }
+ );
+
+ info("Write cookies in the cross-site iframe");
+ await SpecialPowers.spawn(crossSiteBc, [], async _ => {
+ const cookies = [
+ "foo=crossBar; SameSite=None; Secure",
+ "fooLax=crossBarLax; SameSite=Lax; Secure",
+ "fooPartitioned=crossBar; SameSite=None; Secure; Partitioned;",
+ "fooLaxPartitioned=crossBarLax; SameSite=Lax; Secure; Partitioned;",
+ ];
+
+ let query = "";
+
+ for (let cookie of cookies) {
+ query += `Set-Cookie=${cookie}&`;
+ }
+
+ await content.fetch(`cookies.sjs?${query}`);
+ });
+
+ info(
+ "Register a service worker and trigger a fetch request to get cookies in cross-site context."
+ );
+ await registerSW(crossSiteBc);
+ let cookieStr = await fetchCookiesFromSW(crossSiteBc);
+
+ is(
+ cookieStr,
+ "fooPartitioned=crossBar",
+ "Only the SameSite=None partitioned cookie set in the third-party iframe is available."
+ );
+
+ info("Set cookies from the third-party service worker.");
+ await setCookiesFromSW(crossSiteBc, [
+ "foo=crossBarSW; SameSite=None; Secure",
+ "fooLax=crossBarLaxSW; SameSite=Lax; Secure",
+ "fooPartitioned=crossBarSW; SameSite=None; Secure; Partitioned;",
+ "fooLaxPartitioned=crossBarLaxSW; SameSite=Lax; Secure; Partitioned;",
+ ]);
+
+ info("Get cookies from the third-party service worker.");
+ cookieStr = await fetchCookiesFromSW(crossSiteBc);
+
+ is(
+ cookieStr,
+ "fooPartitioned=crossBarSW",
+ "Only the SameSite=None partitioned cookie set in the third-party service worker is available."
+ );
+
+ await unregisterSW(crossSiteBc);
+ BrowserTestUtils.removeTab(tab);
+ Services.cookies.removeAll();
+});
+
+/**
+ * Verify a ABA service worker can only access cookies set in the ABA context.
+ */
+add_task(async function testCookiesWithABAServiceWorker() {
+ // Disable blocking third-party cookies.
+ await SpecialPowers.pushPrefEnv({
+ set: [["network.cookie.cookieBehavior.optInPartitioning", false]],
+ });
+
+ info("Open a tab");
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ TEST_TOP_PAGE
+ );
+
+ info("Writing cookies to the first-party context.");
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async _ => {
+ const cookies = [
+ "foo=bar; SameSite=None; Secure",
+ "fooLax=barLax; SameSite=Lax; Secure",
+ ];
+
+ let query = "";
+
+ for (let cookie of cookies) {
+ query += `Set-Cookie=${cookie}&`;
+ }
+
+ await content.fetch(`cookies.sjs?${query}`);
+ });
+
+ info("Load a ABA iframe");
+ let crossSiteBc = await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [TEST_CROSS_SITE_PAGE],
+ async url => {
+ let ifr = content.document.createElement("iframe");
+
+ await new content.Promise(resolve => {
+ ifr.onload = resolve;
+ content.document.body.appendChild(ifr);
+ ifr.src = url;
+ });
+
+ return ifr.browsingContext;
+ }
+ );
+
+ let ABABc = await SpecialPowers.spawn(
+ crossSiteBc,
+ [TEST_TOP_PAGE],
+ async url => {
+ let ifr = content.document.createElement("iframe");
+
+ await new content.Promise(resolve => {
+ ifr.onload = resolve;
+ content.document.body.appendChild(ifr);
+ ifr.src = url;
+ });
+
+ return ifr.browsingContext;
+ }
+ );
+
+ info(
+ "Register a service worker and trigger a fetch request to get cookies in the ABA context."
+ );
+
+ await registerSW(ABABc);
+ let cookieStr = await fetchCookiesFromSW(ABABc);
+ is(cookieStr, "", "No cookie should be available in ABA context.");
+
+ info("Set cookies in the ABA iframe");
+ await SpecialPowers.spawn(ABABc, [], async _ => {
+ const cookies = [
+ "fooABA=barABA; SameSite=None; Secure",
+ "fooABALax=BarABALax; SameSite=Lax; Secure",
+ ];
+
+ let query = "";
+
+ for (let cookie of cookies) {
+ query += `Set-Cookie=${cookie}&`;
+ }
+
+ await content.fetch(`cookies.sjs?${query}`);
+ });
+
+ info("Get cookies in the ABA service worker.");
+ cookieStr = await fetchCookiesFromSW(ABABc);
+
+ is(
+ cookieStr,
+ "fooABA=barABA",
+ "Only the SameSite=None cookie set in ABA iframe is available."
+ );
+
+ info("Set cookies from the service worker in ABA context");
+ await setCookiesFromSW(ABABc, [
+ "fooABA=barABASW; SameSite=None; Secure",
+ "fooABALax=BarABALaxSW; SameSite=Lax; Secure",
+ ]);
+
+ info("Get cookies from the service worker in the ABA context.");
+ cookieStr = await fetchCookiesFromSW(ABABc);
+
+ is(
+ cookieStr,
+ "fooABA=barABASW",
+ "Only the SameSite=None cookie set in ABA service worker is available."
+ );
+
+ await unregisterSW(ABABc);
+ BrowserTestUtils.removeTab(tab);
+ Services.cookies.removeAll();
+});
+
+/**
+ * Verify a ABA service worker can only access partitioned cookies set in the
+ * ABA context if third-party cookies are blocked.
+ */
+add_task(async function testCookiesWithABAServiceWorker() {
+ // Disable blocking third-party cookies.
+ await SpecialPowers.pushPrefEnv({
+ set: [["network.cookie.cookieBehavior.optInPartitioning", true]],
+ });
+
+ info("Open a tab");
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ TEST_TOP_PAGE
+ );
+
+ info("Load a ABA iframe");
+ let crossSiteBc = await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [TEST_CROSS_SITE_PAGE],
+ async url => {
+ let ifr = content.document.createElement("iframe");
+
+ await new content.Promise(resolve => {
+ ifr.onload = resolve;
+ content.document.body.appendChild(ifr);
+ ifr.src = url;
+ });
+
+ return ifr.browsingContext;
+ }
+ );
+
+ let ABABc = await SpecialPowers.spawn(
+ crossSiteBc,
+ [TEST_TOP_PAGE],
+ async url => {
+ let ifr = content.document.createElement("iframe");
+
+ await new content.Promise(resolve => {
+ ifr.onload = resolve;
+ content.document.body.appendChild(ifr);
+ ifr.src = url;
+ });
+
+ return ifr.browsingContext;
+ }
+ );
+
+ info("Set cookies in the ABA iframe");
+ await SpecialPowers.spawn(ABABc, [], async _ => {
+ const cookies = [
+ "fooABA=barABA; SameSite=None; Secure",
+ "fooABALax=BarABALax; SameSite=Lax; Secure",
+ "fooABAPartitioned=barABA; SameSite=None; Secure; Partitioned;",
+ "fooABALaxPartitioned=BarABALax; SameSite=Lax; Secure; Partitioned;",
+ ];
+
+ let query = "";
+
+ for (let cookie of cookies) {
+ query += `Set-Cookie=${cookie}&`;
+ }
+
+ await content.fetch(`cookies.sjs?${query}`);
+ });
+
+ info(
+ "Register a service worker and trigger a fetch request to get cookies in the ABA context."
+ );
+
+ await registerSW(ABABc);
+
+ info("Get cookies in the ABA service worker.");
+ let cookieStr = await fetchCookiesFromSW(ABABc);
+
+ is(
+ cookieStr,
+ "fooABAPartitioned=barABA",
+ "Only the SameSite=None partitioned cookie set in ABA iframe is available."
+ );
+
+ info("Set cookies from the service worker in ABA context");
+ await setCookiesFromSW(ABABc, [
+ "fooABA=barABASW; SameSite=None; Secure",
+ "fooABALax=BarABALaxSW; SameSite=Lax; Secure",
+ "fooABAPartitioned=barABASW; SameSite=None; Secure; Partitioned;",
+ "fooABALaxPartitioned=BarABALaxSW; SameSite=Lax; Secure; Partitioned;",
+ ]);
+
+ info("Get cookies from the service worker in the ABA context.");
+ cookieStr = await fetchCookiesFromSW(ABABc);
+
+ is(
+ cookieStr,
+ "fooABAPartitioned=barABASW",
+ "Only the SameSite=None partitioned cookie set in ABA service worker is available."
+ );
+
+ await unregisterSW(ABABc);
+ BrowserTestUtils.removeTab(tab);
+ Services.cookies.removeAll();
+});
diff --git a/netwerk/cookie/test/browser/chips.sjs b/netwerk/cookie/test/browser/chips.sjs
new file mode 100644
index 0000000000..e60109f6fa
--- /dev/null
+++ b/netwerk/cookie/test/browser/chips.sjs
@@ -0,0 +1,28 @@
+function handleRequest(aRequest, aResponse) {
+ aResponse.setStatusLine(aRequest.httpVersion, 200);
+
+ var params = new URLSearchParams(aRequest.queryString);
+
+ // Get Cookie header string.
+ if (params.has("get")) {
+ if (aRequest.hasHeader("Cookie")) {
+ let cookie = aRequest.getHeader("Cookie");
+ aResponse.write(cookie);
+ }
+ return;
+ }
+
+ // Set a partitioned and a unpartitioned cookie.
+ if (params.has("set")) {
+ aResponse.setHeader(
+ "Set-Cookie",
+ "cookie=partitioned; Partitioned; SameSite=None; Secure",
+ true
+ );
+ aResponse.setHeader(
+ "Set-Cookie",
+ "cookie=unpartitioned; SameSite=None; Secure",
+ true
+ );
+ }
+}
diff --git a/netwerk/cookie/test/browser/cookies.sjs b/netwerk/cookie/test/browser/cookies.sjs
new file mode 100644
index 0000000000..9beb861d44
--- /dev/null
+++ b/netwerk/cookie/test/browser/cookies.sjs
@@ -0,0 +1,17 @@
+function handleRequest(aRequest, aResponse) {
+ aResponse.setStatusLine(aRequest.httpVersion, 200);
+ let query = new URLSearchParams(aRequest.queryString);
+
+ if (query.has("Set-Cookie")) {
+ for (let value of query.getAll("Set-Cookie")) {
+ aResponse.setHeader("Set-Cookie", value, true);
+ }
+ return;
+ }
+
+ let cookieStr = "";
+ if (aRequest.hasHeader("Cookie")) {
+ cookieStr = aRequest.getHeader("Cookie");
+ }
+ aResponse.write(cookieStr);
+}
diff --git a/netwerk/cookie/test/browser/serviceWorker.js b/netwerk/cookie/test/browser/serviceWorker.js
new file mode 100644
index 0000000000..b2eab40ce4
--- /dev/null
+++ b/netwerk/cookie/test/browser/serviceWorker.js
@@ -0,0 +1,21 @@
+self.addEventListener("install", function () {
+ self.skipWaiting();
+});
+
+self.addEventListener("activate", function (event) {
+ event.waitUntil(self.clients.claim());
+});
+
+self.addEventListener("message", function (event) {
+ if (event.data.action === "fetch") {
+ fetch(event.data.url)
+ .then(response => response.text())
+ .then(data => {
+ self.clients.matchAll().then(clients => {
+ clients.forEach(client => {
+ client.postMessage({ content: data });
+ });
+ });
+ });
+ }
+});
diff --git a/netwerk/dns/DNS.cpp b/netwerk/dns/DNS.cpp
index 91730989db..31d910851b 100644
--- a/netwerk/dns/DNS.cpp
+++ b/netwerk/dns/DNS.cpp
@@ -21,36 +21,6 @@
namespace mozilla {
namespace net {
-const char* inet_ntop_internal(int af, const void* src, char* dst,
- socklen_t size) {
-#ifdef XP_WIN
- if (af == AF_INET) {
- struct sockaddr_in s;
- memset(&s, 0, sizeof(s));
- s.sin_family = AF_INET;
- memcpy(&s.sin_addr, src, sizeof(struct in_addr));
- int result = getnameinfo((struct sockaddr*)&s, sizeof(struct sockaddr_in),
- dst, size, nullptr, 0, NI_NUMERICHOST);
- if (result == 0) {
- return dst;
- }
- } else if (af == AF_INET6) {
- struct sockaddr_in6 s;
- memset(&s, 0, sizeof(s));
- s.sin6_family = AF_INET6;
- memcpy(&s.sin6_addr, src, sizeof(struct in_addr6));
- int result = getnameinfo((struct sockaddr*)&s, sizeof(struct sockaddr_in6),
- dst, size, nullptr, 0, NI_NUMERICHOST);
- if (result == 0) {
- return dst;
- }
- }
- return nullptr;
-#else
- return inet_ntop(af, src, dst, size);
-#endif
-}
-
// Copies the contents of a PRNetAddr to a NetAddr.
// Does not do a ptr safety check!
void PRNetAddrToNetAddr(const PRNetAddr* prAddr, NetAddr* addr) {
@@ -135,7 +105,7 @@ bool NetAddr::ToStringBuffer(char* buf, uint32_t bufSize) const {
}
struct in_addr nativeAddr = {};
nativeAddr.s_addr = addr->inet.ip;
- return !!inet_ntop_internal(AF_INET, &nativeAddr, buf, bufSize);
+ return !!inet_ntop(AF_INET, &nativeAddr, buf, bufSize);
}
if (addr->raw.family == AF_INET6) {
if (bufSize < INET6_ADDRSTRLEN) {
@@ -143,7 +113,7 @@ bool NetAddr::ToStringBuffer(char* buf, uint32_t bufSize) const {
}
struct in6_addr nativeAddr = {};
memcpy(&nativeAddr.s6_addr, &addr->inet6.ip, sizeof(addr->inet6.ip.u8));
- return !!inet_ntop_internal(AF_INET6, &nativeAddr, buf, bufSize);
+ return !!inet_ntop(AF_INET6, &nativeAddr, buf, bufSize);
}
#if defined(XP_UNIX)
if (addr->raw.family == AF_LOCAL) {
diff --git a/netwerk/dns/PlatformDNSAndroid.cpp b/netwerk/dns/PlatformDNSAndroid.cpp
index 171797b938..7875ea7dec 100644
--- a/netwerk/dns/PlatformDNSAndroid.cpp
+++ b/netwerk/dns/PlatformDNSAndroid.cpp
@@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GetAddrInfo.h"
+#include "mozilla/glean/GleanMetrics.h"
#include "mozilla/net/DNSPacket.h"
#include "nsIDNSService.h"
#include "mozilla/Maybe.h"
@@ -71,6 +72,7 @@ nsresult ResolveHTTPSRecordImpl(const nsACString& aHost, uint16_t aFlags,
}
LOG("resolving %s\n", host.get());
+ TimeStamp startTime = TimeStamp::Now();
// Perform the query
rv = packet.FillBuffer(
[&](unsigned char response[DNSPacket::MAX_SIZE]) -> int {
@@ -118,6 +120,8 @@ nsresult ResolveHTTPSRecordImpl(const nsACString& aHost, uint16_t aFlags,
return len - 8;
});
+ mozilla::glean::networking::dns_native_https_call_time.AccumulateRawDuration(
+ TimeStamp::Now() - startTime);
if (NS_FAILED(rv)) {
LOG("failed rv");
return rv;
diff --git a/netwerk/dns/PlatformDNSUnix.cpp b/netwerk/dns/PlatformDNSUnix.cpp
index c7f57fcdda..8a328f3da5 100644
--- a/netwerk/dns/PlatformDNSUnix.cpp
+++ b/netwerk/dns/PlatformDNSUnix.cpp
@@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GetAddrInfo.h"
+#include "mozilla/glean/GleanMetrics.h"
#include "mozilla/net/DNSPacket.h"
#include "nsIDNSService.h"
#include "mozilla/Maybe.h"
@@ -55,6 +56,7 @@ nsresult ResolveHTTPSRecordImpl(const nsACString& aHost, uint16_t aFlags,
rv = packet.FillBuffer(
[&](unsigned char response[DNSPacket::MAX_SIZE]) -> int {
int len = 0;
+ TimeStamp startTime = TimeStamp::Now();
#if defined(HAVE_RES_NINIT)
len = res_nquery(sThreadRes.get(), host.get(), ns_c_in,
nsIDNSService::RESOLVE_TYPE_HTTPSSVC, response,
@@ -65,6 +67,8 @@ nsresult ResolveHTTPSRecordImpl(const nsACString& aHost, uint16_t aFlags,
response, DNSPacket::MAX_SIZE);
#endif
+ mozilla::glean::networking::dns_native_https_call_time
+ .AccumulateRawDuration(TimeStamp::Now() - startTime);
if (len < 0) {
LOG("DNS query failed");
}
diff --git a/netwerk/dns/PlatformDNSWin.cpp b/netwerk/dns/PlatformDNSWin.cpp
index 42f1483ec3..93e936f4dc 100644
--- a/netwerk/dns/PlatformDNSWin.cpp
+++ b/netwerk/dns/PlatformDNSWin.cpp
@@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GetAddrInfo.h"
+#include "mozilla/glean/GleanMetrics.h"
#include "mozilla/net/DNSPacket.h"
#include "nsIDNSService.h"
#include "mozilla/Maybe.h"
@@ -39,9 +40,15 @@ nsresult ResolveHTTPSRecordImpl(const nsACString& aHost, uint16_t aFlags,
return NS_ERROR_UNKNOWN_HOST;
}
+ TimeStamp startTime = TimeStamp::Now();
+
DNS_STATUS status =
DnsQuery_A(host.get(), nsIDNSService::RESOLVE_TYPE_HTTPSSVC,
DNS_QUERY_STANDARD, nullptr, &result, nullptr);
+
+ mozilla::glean::networking::dns_native_https_call_time.AccumulateRawDuration(
+ TimeStamp::Now() - startTime);
+
if (status != ERROR_SUCCESS) {
LOG("DnsQuery_A failed with error: %ld\n", status);
return NS_ERROR_UNKNOWN_HOST;
diff --git a/netwerk/dns/TRRService.cpp b/netwerk/dns/TRRService.cpp
index fbaa67ee14..4599e7b5c0 100644
--- a/netwerk/dns/TRRService.cpp
+++ b/netwerk/dns/TRRService.cpp
@@ -170,7 +170,7 @@ static void EventTelemetryPrefChanged(const char* aPref, void* aData) {
StaticPrefs::network_trr_confirmation_telemetry_enabled());
}
-nsresult TRRService::Init() {
+nsresult TRRService::Init(bool aNativeHTTPSQueryEnabled) {
MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
if (mInitialized) {
return NS_OK;
@@ -189,6 +189,7 @@ nsresult TRRService::Init() {
sTRRServicePtr = this;
+ mNativeHTTPSQueryEnabled = aNativeHTTPSQueryEnabled;
ReadPrefs(nullptr);
mConfirmation.HandleEvent(ConfirmationEvent::Init);
@@ -1021,7 +1022,9 @@ bool TRRService::IsExcludedFromTRR_unlocked(const nsACString& aHost) {
return true;
}
if (mDNSSuffixDomains.Contains(subdomain)) {
- LOG(("Subdomain [%s] of host [%s] Is Excluded From TRR via pref\n",
+ LOG(
+ ("Subdomain [%s] of host [%s] Is Excluded From TRR via DNSSuffix "
+ "domains\n",
subdomain.BeginReading(), aHost.BeginReading()));
return true;
}
diff --git a/netwerk/dns/TRRService.h b/netwerk/dns/TRRService.h
index 3283a8ea06..4c757bd90f 100644
--- a/netwerk/dns/TRRService.h
+++ b/netwerk/dns/TRRService.h
@@ -42,7 +42,7 @@ class TRRService : public TRRServiceBase,
bool OnWritingThread() const override { return NS_IsMainThread(); }
- nsresult Init();
+ nsresult Init(bool aNativeHTTPSQueryEnabled);
nsresult Start();
bool Enabled(nsIRequest::TRRMode aRequestMode = nsIRequest::TRR_DEFAULT_MODE);
bool IsConfirmed() { return mConfirmation.State() == CONFIRM_OK; }
diff --git a/netwerk/dns/TRRServiceBase.cpp b/netwerk/dns/TRRServiceBase.cpp
index 943edc41dd..31d09f3720 100644
--- a/netwerk/dns/TRRServiceBase.cpp
+++ b/netwerk/dns/TRRServiceBase.cpp
@@ -163,8 +163,9 @@ void TRRServiceBase::OnTRRModeChange() {
}
static bool readHosts = false;
+ // When native HTTPS query is enabled, we need to read etc/hosts.
if ((mMode == nsIDNSService::MODE_TRRFIRST ||
- mMode == nsIDNSService::MODE_TRRONLY) &&
+ mMode == nsIDNSService::MODE_TRRONLY || mNativeHTTPSQueryEnabled) &&
!readHosts) {
readHosts = true;
ReadEtcHostsFile();
diff --git a/netwerk/dns/TRRServiceBase.h b/netwerk/dns/TRRServiceBase.h
index a7f85fc95d..f79e31cdb3 100644
--- a/netwerk/dns/TRRServiceBase.h
+++ b/netwerk/dns/TRRServiceBase.h
@@ -82,6 +82,7 @@ class TRRServiceBase : public nsIProxyConfigChangedCallback {
Atomic<bool, Relaxed> mURISetByDetection{false};
Atomic<bool, Relaxed> mTRRConnectionInfoInited{false};
DataMutex<RefPtr<nsHttpConnectionInfo>> mDefaultTRRConnectionInfo;
+ bool mNativeHTTPSQueryEnabled{false};
};
} // namespace net
diff --git a/netwerk/dns/effective_tld_names.dat b/netwerk/dns/effective_tld_names.dat
index fdcaca41d5..d4886d518b 100644
--- a/netwerk/dns/effective_tld_names.dat
+++ b/netwerk/dns/effective_tld_names.dat
@@ -6710,7 +6710,7 @@ org.zw
// newGTLDs
-// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2024-05-04T15:12:50Z
+// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2024-05-31T15:16:08Z
// This list is auto-generated, don't edit it manually.
// aaa : American Automobile Association, Inc.
// https://www.iana.org/domains/root/db/aaa.html
@@ -8976,7 +8976,7 @@ lotte
// https://www.iana.org/domains/root/db/lotto.html
lotto
-// love : Merchant Law Group LLP
+// love : Waterford Limited
// https://www.iana.org/domains/root/db/love.html
love
@@ -11387,9 +11387,9 @@ auth-fips.us-west-2.amazoncognito.com
// Amazon EC2
// Submitted by Luke Wells <psl-maintainers@amazon.com>
// Reference: 4c38fa71-58ac-4768-99e5-689c1767e537
+*.compute.amazonaws.com.cn
*.compute.amazonaws.com
*.compute-1.amazonaws.com
-*.compute.amazonaws.com.cn
us-east-1.amazonaws.com
// Amazon EMR
@@ -12288,26 +12288,26 @@ ju.mp
// CentralNic : http://www.centralnic.com/names/domains
// Submitted by registry <gavin.brown@centralnic.com>
-ae.org
+za.bz
br.com
cn.com
-com.de
-com.se
de.com
eu.com
-gb.net
-hu.net
-jp.net
jpn.com
mex.com
ru.com
sa.com
-se.net
uk.com
-uk.net
us.com
-za.bz
za.com
+com.de
+gb.net
+hu.net
+jp.net
+se.net
+uk.net
+ae.org
+com.se
// No longer operated by CentralNic, these entries should be adopted and/or removed by current operators
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
@@ -12328,8 +12328,8 @@ gr.com
// Radix FZC : http://domains.in.net
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
-in.net
web.in
+in.net
// US REGISTRY LLC : http://us.org
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
@@ -12367,7 +12367,10 @@ discourse.team
// Clever Cloud : https://www.clever-cloud.com/
// Submitted by Quentin Adam <noc@clever-cloud.com>
+cleverapps.cc
+*.services.clever-cloud.com
cleverapps.io
+cleverapps.tech
// Clerk : https://www.clerk.dev
// Submitted by Colin Sidoti <systems@clerk.dev>
@@ -12398,8 +12401,8 @@ cloudaccess.net
// cloudControl : https://www.cloudcontrol.com/
// Submitted by Tobias Wilken <tw@cloudcontrol.com>
-cloudcontrolled.com
cloudcontrolapp.com
+cloudcontrolled.com
// Cloudera, Inc. : https://www.cloudera.com/
// Submitted by Kedarnath Waikar <security@cloudera.com>
@@ -12439,11 +12442,11 @@ co.cz
// Submitted by Jan Krpes <jan.krpes@cdn77.com>
cdn77-storage.com
rsc.contentproxy9.cz
-cdn77-ssl.net
r.cdn77.net
-ssl.origin.cdn77-secure.org
+cdn77-ssl.net
c.cdn77.org
rsc.cdn77.org
+ssl.origin.cdn77-secure.org
// Cloud DNS Ltd : http://www.cloudns.net
// Submitted by Aleksander Hristov <noc@cloudns.net> & Boyan Peychev <boyan@cloudns.net>
@@ -12506,8 +12509,8 @@ test.ru
// COSIMO GmbH : http://www.cosimo.de
// Submitted by Rene Marticke <rmarticke@cosimo.de>
dyn.cosidns.de
-dynamisches-dns.de
dnsupdater.de
+dynamisches-dns.de
internet-dns.de
l-o-g-i-n.de
dynamic-dns.info
@@ -12561,9 +12564,9 @@ cyon.site
// Danger Science Group: https://dangerscience.com/
// Submitted by Skylar MacDonald <skylar@dangerscience.com>
+platform0.app
fnwk.site
folionetwork.site
-platform0.app
// Daplie, Inc : https://daplie.com
// Submitted by AJ ONeal <aj@daplie.com>
@@ -12693,6 +12696,26 @@ dy.fi
tunk.org
// DynDNS.com : http://www.dyndns.com/services/dns/dyndns/
+dyndns.biz
+for-better.biz
+for-more.biz
+for-some.biz
+for-the.biz
+selfip.biz
+webhop.biz
+ftpaccess.cc
+game-server.cc
+myphotos.cc
+scrapping.cc
+blogdns.com
+cechire.com
+dnsalias.com
+dnsdojo.com
+doesntexist.com
+dontexist.com
+doomdns.com
+dyn-o-saur.com
+dynalias.com
dyndns-at-home.com
dyndns-at-work.com
dyndns-blog.com
@@ -12707,64 +12730,14 @@ dyndns-server.com
dyndns-web.com
dyndns-wiki.com
dyndns-work.com
-dyndns.biz
-dyndns.info
-dyndns.org
-dyndns.tv
-at-band-camp.net
-ath.cx
-barrel-of-knowledge.info
-barrell-of-knowledge.info
-better-than.tv
-blogdns.com
-blogdns.net
-blogdns.org
-blogsite.org
-boldlygoingnowhere.org
-broke-it.net
-buyshouses.net
-cechire.com
-dnsalias.com
-dnsalias.net
-dnsalias.org
-dnsdojo.com
-dnsdojo.net
-dnsdojo.org
-does-it.net
-doesntexist.com
-doesntexist.org
-dontexist.com
-dontexist.net
-dontexist.org
-doomdns.com
-doomdns.org
-dvrdns.org
-dyn-o-saur.com
-dynalias.com
-dynalias.net
-dynalias.org
-dynathome.net
-dyndns.ws
-endofinternet.net
-endofinternet.org
-endoftheinternet.org
est-a-la-maison.com
est-a-la-masion.com
est-le-patron.com
est-mon-blogueur.com
-for-better.biz
-for-more.biz
-for-our.info
-for-some.biz
-for-the.biz
-forgot.her.name
-forgot.his.name
from-ak.com
from-al.com
from-ar.com
-from-az.net
from-ca.com
-from-co.net
from-ct.com
from-dc.com
from-de.com
@@ -12777,10 +12750,8 @@ from-il.com
from-in.com
from-ks.com
from-ky.com
-from-la.net
from-ma.com
from-md.com
-from-me.org
from-mi.com
from-mn.com
from-mo.com
@@ -12793,7 +12764,6 @@ from-nh.com
from-nj.com
from-nm.com
from-nv.com
-from-ny.net
from-oh.com
from-ok.com
from-or.com
@@ -12811,45 +12781,18 @@ from-wa.com
from-wi.com
from-wv.com
from-wy.com
-ftpaccess.cc
-fuettertdasnetz.de
-game-host.org
-game-server.cc
getmyip.com
-gets-it.net
-go.dyndns.org
gotdns.com
-gotdns.org
-groks-the.info
-groks-this.info
-ham-radio-op.net
-here-for-more.info
hobby-site.com
-hobby-site.org
-home.dyndns.org
-homedns.org
-homeftp.net
-homeftp.org
-homeip.net
homelinux.com
-homelinux.net
-homelinux.org
homeunix.com
-homeunix.net
-homeunix.org
iamallama.com
-in-the-band.net
is-a-anarchist.com
is-a-blogger.com
is-a-bookkeeper.com
-is-a-bruinsfan.org
is-a-bulls-fan.com
-is-a-candidate.org
is-a-caterer.com
-is-a-celticsfan.org
is-a-chef.com
-is-a-chef.net
-is-a-chef.org
is-a-conservative.com
is-a-cpa.com
is-a-cubicle-slave.com
@@ -12858,31 +12801,25 @@ is-a-designer.com
is-a-doctor.com
is-a-financialadvisor.com
is-a-geek.com
-is-a-geek.net
-is-a-geek.org
is-a-green.com
is-a-guru.com
is-a-hard-worker.com
is-a-hunter.com
-is-a-knight.org
is-a-landscaper.com
is-a-lawyer.com
is-a-liberal.com
is-a-libertarian.com
-is-a-linux-user.org
is-a-llama.com
is-a-musician.com
is-a-nascarfan.com
is-a-nurse.com
is-a-painter.com
-is-a-patsfan.org
is-a-personaltrainer.com
is-a-photographer.com
is-a-player.com
is-a-republican.com
is-a-rockstar.com
is-a-socialist.com
-is-a-soxfan.org
is-a-student.com
is-a-teacher.com
is-a-techie.com
@@ -12894,92 +12831,158 @@ is-an-anarchist.com
is-an-artist.com
is-an-engineer.com
is-an-entertainer.com
-is-by.us
is-certified.com
-is-found.org
is-gone.com
is-into-anime.com
is-into-cars.com
is-into-cartoons.com
is-into-games.com
is-leet.com
-is-lost.org
is-not-certified.com
-is-saved.org
is-slick.com
is-uberleet.com
-is-very-bad.org
-is-very-evil.org
-is-very-good.org
-is-very-nice.org
-is-very-sweet.org
is-with-theband.com
isa-geek.com
-isa-geek.net
-isa-geek.org
isa-hockeynut.com
issmarterthanyou.com
+likes-pie.com
+likescandy.com
+neat-url.com
+saves-the-whales.com
+selfip.com
+sells-for-less.com
+sells-for-u.com
+servebbs.com
+simple-url.com
+space-to-rent.com
+teaches-yoga.com
+writesthisblog.com
+ath.cx
+fuettertdasnetz.de
isteingeek.de
istmein.de
-kicks-ass.net
-kicks-ass.org
-knowsitall.info
-land-4-sale.us
lebtimnetz.de
leitungsen.de
-likes-pie.com
-likescandy.com
+traeumtgerade.de
+barrel-of-knowledge.info
+barrell-of-knowledge.info
+dyndns.info
+for-our.info
+groks-the.info
+groks-this.info
+here-for-more.info
+knowsitall.info
+selfip.info
+webhop.info
+forgot.her.name
+forgot.his.name
+at-band-camp.net
+blogdns.net
+broke-it.net
+buyshouses.net
+dnsalias.net
+dnsdojo.net
+does-it.net
+dontexist.net
+dynalias.net
+dynathome.net
+endofinternet.net
+from-az.net
+from-co.net
+from-la.net
+from-ny.net
+gets-it.net
+ham-radio-op.net
+homeftp.net
+homeip.net
+homelinux.net
+homeunix.net
+in-the-band.net
+is-a-chef.net
+is-a-geek.net
+isa-geek.net
+kicks-ass.net
+office-on-the.net
+podzone.net
+scrapper-site.net
+selfip.net
+sells-it.net
+servebbs.net
+serveftp.net
+thruhere.net
+webhop.net
merseine.nu
mine.nu
+shacknet.nu
+blogdns.org
+blogsite.org
+boldlygoingnowhere.org
+dnsalias.org
+dnsdojo.org
+doesntexist.org
+dontexist.org
+doomdns.org
+dvrdns.org
+dynalias.org
+dyndns.org
+go.dyndns.org
+home.dyndns.org
+endofinternet.org
+endoftheinternet.org
+from-me.org
+game-host.org
+gotdns.org
+hobby-site.org
+homedns.org
+homeftp.org
+homelinux.org
+homeunix.org
+is-a-bruinsfan.org
+is-a-candidate.org
+is-a-celticsfan.org
+is-a-chef.org
+is-a-geek.org
+is-a-knight.org
+is-a-linux-user.org
+is-a-patsfan.org
+is-a-soxfan.org
+is-found.org
+is-lost.org
+is-saved.org
+is-very-bad.org
+is-very-evil.org
+is-very-good.org
+is-very-nice.org
+is-very-sweet.org
+isa-geek.org
+kicks-ass.org
misconfused.org
-mypets.ws
-myphotos.cc
-neat-url.com
-office-on-the.net
-on-the-web.tv
-podzone.net
podzone.org
readmyblog.org
-saves-the-whales.com
-scrapper-site.net
-scrapping.cc
-selfip.biz
-selfip.com
-selfip.info
-selfip.net
selfip.org
-sells-for-less.com
-sells-for-u.com
-sells-it.net
sellsyourhome.org
-servebbs.com
-servebbs.net
servebbs.org
-serveftp.net
serveftp.org
servegame.org
-shacknet.nu
-simple-url.com
-space-to-rent.com
stuff-4-sale.org
-stuff-4-sale.us
-teaches-yoga.com
-thruhere.net
-traeumtgerade.de
-webhop.biz
-webhop.info
-webhop.net
webhop.org
+better-than.tv
+dyndns.tv
+on-the-web.tv
worse-than.tv
-writesthisblog.com
+is-by.us
+land-4-sale.us
+stuff-4-sale.us
+dyndns.ws
+mypets.ws
// ddnss.de : https://www.ddnss.de/
// Submitted by Robert Niedziela <webmaster@ddnss.de>
ddnss.de
dyn.ddnss.de
dyndns.ddnss.de
-dyndns1.de
dyn-ip24.de
+dyndns1.de
home-webserver.de
dyn.home-webserver.de
myhome-server.de
@@ -12987,8 +12990,8 @@ ddnss.org
// Definima : http://www.definima.com/
// Submitted by Maxence Bitterli <maxence@definima.com>
-definima.net
definima.io
+definima.net
// DigitalOcean App Platform : https://www.digitalocean.com/products/app-platform/
// Submitted by Braxton Huggins <psl-maintainers@digitalocean.com>
@@ -13153,6 +13156,11 @@ us-2.evennode.com
us-3.evennode.com
us-4.evennode.com
+// Expo : https://expo.dev/
+// Submitted by James Ide <psl@expo.dev>
+expo.app
+staging.expo.app
+
// eDirect Corp. : https://hosting.url.com.tw/
// Submitted by C.S. chang <cschang@corp.url.com.tw>
twmail.cc
@@ -13251,8 +13259,6 @@ u.channelsdvr.net
edgecompute.app
fastly-edge.com
fastly-terrarium.com
-fastlylb.net
-map.fastlylb.net
freetls.fastly.net
map.fastly.net
a.prod.fastly.net
@@ -13260,6 +13266,8 @@ global.prod.fastly.net
a.ssl.fastly.net
b.ssl.fastly.net
global.ssl.fastly.net
+fastlylb.net
+map.fastlylb.net
// Fastmail : https://www.fastmail.com/
// Submitted by Marc Bradshaw <marc@fastmailteam.com>
@@ -13329,8 +13337,8 @@ flutterflow.app
// fly.io: https://fly.io
// Submitted by Kurt Mackey <kurt@fly.io>
fly.dev
-edgeapp.net
shw.io
+edgeapp.net
// Flynn : https://flynn.io
// Submitted by Jonathan Rudenberg <jonathan@flynn.io>
@@ -13419,6 +13427,8 @@ aliases121.com
// GDS : https://www.gov.uk/service-manual/technology/managing-domain-names
// Submitted by Stephen Ford <hostmaster@digital.cabinet-office.gov.uk>
+campaign.gov.uk
+service.gov.uk
independent-commission.uk
independent-inquest.uk
independent-inquiry.uk
@@ -13426,8 +13436,6 @@ independent-panel.uk
independent-review.uk
public-inquiry.uk
royal-commission.uk
-campaign.gov.uk
-service.gov.uk
// CDDO : https://www.gov.uk/guidance/get-an-api-domain-on-govuk
// Submitted by Jamie Tanna <jamie.tanna@digital.cabinet-office.gov.uk>
@@ -13615,71 +13623,64 @@ ro.im
goip.de
// Google, Inc.
-// Submitted by Eduardo Vela <evn@google.com>
-*.run.app
-web.app
-*.0emm.com
-appspot.com
-*.r.appspot.com
-codespot.com
-googleapis.com
-googlecode.com
-pagespeedmobilizer.com
-publishproxy.com
-withgoogle.com
-withyoutube.com
-*.gateway.dev
-cloud.goog
-translate.goog
-*.usercontent.goog
-cloudfunctions.net
+// Submitted by Shannon McCabe <public-suffix-editors@google.com>
blogspot.ae
blogspot.al
blogspot.am
+*.hosted.app
+*.run.app
+web.app
+blogspot.com.ar
+blogspot.co.at
+blogspot.com.au
blogspot.ba
blogspot.be
blogspot.bg
blogspot.bj
+blogspot.com.br
+blogspot.com.by
blogspot.ca
blogspot.cf
blogspot.ch
blogspot.cl
-blogspot.co.at
-blogspot.co.id
-blogspot.co.il
-blogspot.co.ke
-blogspot.co.nz
-blogspot.co.uk
-blogspot.co.za
-blogspot.com
-blogspot.com.ar
-blogspot.com.au
-blogspot.com.br
-blogspot.com.by
blogspot.com.co
-blogspot.com.cy
-blogspot.com.ee
-blogspot.com.eg
-blogspot.com.es
-blogspot.com.mt
-blogspot.com.ng
-blogspot.com.tr
-blogspot.com.uy
+*.0emm.com
+appspot.com
+*.r.appspot.com
+blogspot.com
+codespot.com
+googleapis.com
+googlecode.com
+pagespeedmobilizer.com
+publishproxy.com
+withgoogle.com
+withyoutube.com
blogspot.cv
+blogspot.com.cy
blogspot.cz
blogspot.de
+*.gateway.dev
blogspot.dk
+blogspot.com.ee
+blogspot.com.eg
+blogspot.com.es
blogspot.fi
blogspot.fr
+cloud.goog
+translate.goog
+*.usercontent.goog
blogspot.gr
blogspot.hk
blogspot.hr
blogspot.hu
+blogspot.co.id
blogspot.ie
+blogspot.co.il
blogspot.in
blogspot.is
blogspot.it
blogspot.jp
+blogspot.co.ke
blogspot.kr
blogspot.li
blogspot.lt
@@ -13687,10 +13688,14 @@ blogspot.lu
blogspot.md
blogspot.mk
blogspot.mr
+blogspot.com.mt
blogspot.mx
blogspot.my
+cloudfunctions.net
+blogspot.com.ng
blogspot.nl
blogspot.no
+blogspot.co.nz
blogspot.pe
blogspot.pt
blogspot.qa
@@ -13704,9 +13709,13 @@ blogspot.si
blogspot.sk
blogspot.sn
blogspot.td
+blogspot.com.tr
blogspot.tw
blogspot.ug
+blogspot.co.uk
+blogspot.com.uy
blogspot.vn
+blogspot.co.za
// Goupile : https://goupile.fr
// Submitted by Niels Martignene <hello@goupile.fr>
@@ -13739,8 +13748,8 @@ conf.se
// Handshake : https://handshake.org
// Submitted by Mike Damm <md@md.vc>
-hs.zone
hs.run
+hs.zone
// Hashbang : https://hashbang.sh
hashbang.sh
@@ -13813,6 +13822,10 @@ ie.ua
// HostyHosting (hostyhosting.com)
hostyhosting.io
+// Hypernode B.V. : https://www.hypernode.com/
+// Submitted by Cipriano Groenendal <security@nl.team.blue>
+hypernode.io
+
// Häkkinen.fi
// Submitted by Eero Häkkinen <Eero+psl@Häkkinen.fi>
häkkinen.fi
@@ -13833,8 +13846,8 @@ iliadboxos.it
// Impertrix Solutions : <https://impertrixcdn.com>
// Submitted by Zhixiang Zhao <csuite@impertrix.com>
-impertrixcdn.com
impertrix.com
+impertrixcdn.com
// Incsub, LLC: https://incsub.com/
// Submitted by Aaron Edwards <sysadmins@incsub.com>
@@ -13851,10 +13864,10 @@ in-berlin.de
in-brb.de
in-butter.de
in-dsl.de
-in-dsl.net
-in-dsl.org
in-vpn.de
+in-dsl.net
in-vpn.net
+in-dsl.org
in-vpn.org
// info.at : http://www.info.at/
@@ -14029,13 +14042,13 @@ jotelulu.cloud
// JouwWeb B.V. : https://www.jouwweb.nl
// Submitted by Camilo Sperberg <tech@webador.com>
-jouwweb.site
webadorsite.com
+jouwweb.site
// Joyent : https://www.joyent.com/
// Submitted by Brian Bennett <brian.bennett@joyent.com>
-*.triton.zone
*.cns.joyent.com
+*.triton.zone
// JS.ORG : http://dns.js.org
// Submitted by Stefan Keim <admin@js.org>
@@ -14077,8 +14090,8 @@ oya.to
// Katholieke Universiteit Leuven: https://www.kuleuven.be
// Submitted by Abuse KU Leuven <abuse@kuleuven.be>
-kuleuven.cloud
ezproxy.kuleuven.be
+kuleuven.cloud
// .KRD : http://nic.krd/data/krd/Registration%20Policy.pdf
co.krd
@@ -14086,8 +14099,8 @@ edu.krd
// Krellian Ltd. : https://krellian.com
// Submitted by Ben Francis <ben@krellian.com>
-krellian.net
webthings.io
+krellian.net
// LCube - Professional hosting e.K. : https://www.lcube-webhosting.de
// Submitted by Lars Laehn <info@lcube.de>
@@ -14121,8 +14134,8 @@ co.technology
// linkyard ldt: https://www.linkyard.ch/
// Submitted by Mario Siegenthaler <mario.siegenthaler@linkyard.ch>
-linkyard.cloud
linkyard-cloud.ch
+linkyard.cloud
// Linode : https://linode.com
// Submitted by <security@linode.com>
@@ -14177,11 +14190,9 @@ lugs.org.uk
// Lukanet Ltd : https://lukanet.com
// Submitted by Anton Avramov <register@lukanet.com>
barsy.bg
-barsy.co.uk
-barsyonline.co.uk
+barsy.club
barsycenter.com
barsyonline.com
-barsy.club
barsy.de
barsy.eu
barsy.in
@@ -14200,6 +14211,8 @@ barsy.shop
barsy.site
barsy.support
barsy.uk
+barsy.co.uk
+barsyonline.co.uk
// Magento Commerce
// Submitted by Damien Tournoud <dtournoud@magento.cloud>
@@ -14230,8 +14243,8 @@ mcpe.me
// Submitted by Evgeniy Subbotin <e.subbotin@mchost.ru>
mcdir.me
mcdir.ru
-mcpre.ru
vps.mcdir.ru
+mcpre.ru
// Mediatech : https://mediatech.by
// Submitted by Evgeniy Kozhuhovskiy <ugenk@mediatech.by>
@@ -14280,10 +14293,9 @@ co.pl
// Microsoft Azure : https://home.azure
*.azurecontainer.io
azure-api.net
+azure-mobile.net
azureedge.net
azurefd.net
-azurewebsites.net
-azure-mobile.net
azurestaticapps.net
1.azurestaticapps.net
2.azurestaticapps.net
@@ -14297,6 +14309,7 @@ eastasia.azurestaticapps.net
eastus2.azurestaticapps.net
westeurope.azurestaticapps.net
westus2.azurestaticapps.net
+azurewebsites.net
cloudapp.net
trafficmanager.net
blob.core.windows.net
@@ -14335,8 +14348,8 @@ pp.ru
// Mythic Beasts : https://www.mythic-beasts.com
// Submitted by Paul Cammish <kelduum@mythic-beasts.com>
hostedpi.com
-customer.mythic-beasts.com
caracal.mythic-beasts.com
+customer.mythic-beasts.com
fentiger.mythic-beasts.com
lynx.mythic-beasts.com
ocelot.mythic-beasts.com
@@ -14418,6 +14431,10 @@ noop.app
// Submitted by Laurent Pellegrino <security@noticeable.io>
noticeable.news
+// Notion Labs, Inc : https://www.notion.so/
+// Submitted by Jess Yao <trust-core-team@makenotion.com>
+notion.site
+
// Now-DNS : https://now-dns.com
// Submitted by Steve Russell <steve@now-dns.com>
dnsking.ch
@@ -14453,91 +14470,91 @@ nerdpol.ovh
// No-IP.com : https://noip.com/
// Submitted by Deven Reza <publicsuffixlist@noip.com>
+mmafan.biz
+myftp.biz
+no-ip.biz
+no-ip.ca
+fantasyleague.cc
+gotdns.ch
+3utilities.com
blogsyte.com
-brasilia.me
-cable-modem.org
ciscofreak.com
-collegefan.org
-couchpotatofries.org
damnserver.com
-ddns.me
+ddnsking.com
ditchyourip.com
-dnsfor.me
dnsiskinky.com
-dvrcam.info
dynns.com
-eating-organic.net
-fantasyleague.cc
geekgalaxy.com
-golffan.us
health-carereform.com
homesecuritymac.com
homesecuritypc.com
-hopto.me
-ilovecollege.info
-loginto.me
-mlbfan.org
-mmafan.biz
myactivedirectory.com
-mydissent.net
-myeffect.net
-mymediapc.net
-mypsx.net
mysecuritycamera.com
-mysecuritycamera.net
-mysecuritycamera.org
+myvnc.com
net-freaks.com
-nflfan.org
-nhlfan.net
-no-ip.ca
-no-ip.co.uk
-no-ip.net
-noip.us
onthewifi.com
-pgafan.net
point2this.com
-pointto.us
-privatizehealthinsurance.net
quicksytes.com
-read-books.org
securitytactics.com
+servebeer.com
+servecounterstrike.com
serveexchange.com
+serveftp.com
+servegame.com
+servehalflife.com
+servehttp.com
servehumour.com
+serveirc.com
+servemp3.com
servep2p.com
+servepics.com
+servequake.com
servesarcasm.com
stufftoread.com
-ufcfan.org
unusualperson.com
workisboring.com
-3utilities.com
-bounceme.net
-ddns.net
-ddnsking.com
-gotdns.ch
-hopto.org
-myftp.biz
-myftp.org
-myvnc.com
-no-ip.biz
+dvrcam.info
+ilovecollege.info
no-ip.info
-no-ip.org
+brasilia.me
+ddns.me
+dnsfor.me
+hopto.me
+loginto.me
noip.me
+webhop.me
+bounceme.net
+ddns.net
+eating-organic.net
+mydissent.net
+myeffect.net
+mymediapc.net
+mypsx.net
+mysecuritycamera.net
+nhlfan.net
+no-ip.net
+pgafan.net
+privatizehealthinsurance.net
redirectme.net
-servebeer.com
serveblog.net
-servecounterstrike.com
-serveftp.com
-servegame.com
-servehalflife.com
-servehttp.com
-serveirc.com
serveminecraft.net
-servemp3.com
-servepics.com
-servequake.com
sytes.net
-webhop.me
+cable-modem.org
+collegefan.org
+couchpotatofries.org
+hopto.org
+mlbfan.org
+myftp.org
+mysecuritycamera.org
+nflfan.org
+no-ip.org
+read-books.org
+ufcfan.org
zapto.org
+no-ip.co.uk
+golffan.us
+noip.us
+pointto.us
// NodeArt : https://nodeart.io
// Submitted by Konstantin Nosov <Nosov@nodeart.io>
@@ -14557,6 +14574,7 @@ prvcy.page
// Observable, Inc. : https://observablehq.com
// Submitted by Mike Bostock <dns@observablehq.com>
+observablehq.cloud
static.observableusercontent.com
// Octopodal Solutions, LLC. : https://ulterius.io/
@@ -14577,25 +14595,25 @@ omniwe.site
// One.com: https://www.one.com/
// Submitted by Jacob Bunk Nielsen <jbn@one.com>
-123hjemmeside.dk
-123hjemmeside.no
-123homepage.it
-123kotisivu.fi
-123minsida.se
-123miweb.es
-123paginaweb.pt
-123siteweb.fr
123webseite.at
-123webseite.de
123website.be
+simplesite.com.br
123website.ch
+simplesite.com
+123webseite.de
+123hjemmeside.dk
+123miweb.es
+123kotisivu.fi
+123siteweb.fr
+simplesite.gr
+123homepage.it
123website.lu
123website.nl
+123hjemmeside.no
service.one
-simplesite.com
-simplesite.com.br
-simplesite.gr
simplesite.pl
+123paginaweb.pt
+123minsida.se
// One Fold Media : http://www.onefoldmedia.com/
// Submitted by Eddie Jones <eddie@onefoldmedia.com>
@@ -14645,8 +14663,8 @@ outsystemscloud.com
// OVHcloud: https://ovhcloud.com
// Submitted by Vincent Cassé <vincent.casse@ovhcloud.com>
-*.webpaas.ovh.net
*.hosting.ovh.net
+*.webpaas.ovh.net
// OwnProvider GmbH: http://www.ownprovider.com
// Submitted by Jan Moennich <jan.moennich@ownprovider.com>
@@ -14699,8 +14717,8 @@ zakopane.pl
// Pantheon Systems, Inc. : https://pantheon.io/
// Submitted by Gary Dylina <gary@pantheon.io>
-pantheonsite.io
gotpantheon.com
+pantheonsite.io
// Peplink | Pepwave : http://peplink.com/
// Submitted by Steve Leung <steveleung@peplink.com>
@@ -14736,9 +14754,9 @@ platterp.us
// Plesk : https://www.plesk.com/
// Submitted by Anton Akhtyamov <program-managers@plesk.com>
+pleskns.com
pdns.page
plesk.page
-pleskns.com
// Pley AB : https://www.pley.com/
// Submitted by Henning Pohl <infra@pley.com>
@@ -14869,8 +14887,8 @@ g.vbrplsbx.io
// Rancher Labs, Inc : https://rancher.com
// Submitted by Vincent Fiduccia <domains@rancher.com>
-*.on-k3s.io
*.on-rancher.cloud
+*.on-k3s.io
*.on-rio.io
// Read The Docs, Inc : https://www.readthedocs.org
@@ -14883,8 +14901,8 @@ rhcloud.com
// Render : https://render.com
// Submitted by Anurag Goel <dev@render.com>
-app.render.com
onrender.com
+app.render.com
// Repl.it : https://repl.it
// Submitted by Lincoln Bergeson <psl@repl.it>
@@ -15029,8 +15047,8 @@ sandcats.io
// SBE network solutions GmbH : https://www.sbe.de/
// Submitted by Norman Meilick <nm@sbe.de>
-logoip.de
logoip.com
+logoip.de
// Scaleway : https://www.scaleway.com/
// Submitted by Rémy Léone <rleone@scaleway.com>
@@ -15119,6 +15137,10 @@ biz.ua
co.ua
pp.ua
+// Sheezy.Art : https://sheezy.art
+// Submitted by Nyoom <admin@sheezy.art>
+sheezy.games
+
// Shift Crypto AG : https://shiftcrypto.ch
// Submitted by alex <alex@shiftcrypto.ch>
shiftcrypto.dev
@@ -15223,8 +15245,8 @@ stackit.zone
// Staclar : https://staclar.com
// Submitted by Q Misell <q@staclar.com>
-musician.io
// Submitted by Matthias Merkel <matthias.merkel@staclar.com>
+musician.io
novecore.site
// staticland : https://static.land
@@ -15336,8 +15358,8 @@ su.paba.se
// Symfony, SAS : https://symfony.com/
// Submitted by Fabien Potencier <fabien@symfony.com>
-*.s5y.io
*.sensiosite.cloud
+*.s5y.io
// Syncloud : https://syncloud.org
// Submitted by Boris Rybalkin <syncloud@syncloud.it>
@@ -15359,14 +15381,14 @@ dsmynas.net
familyds.net
dsmynas.org
familyds.org
-vpnplus.to
direct.quickconnect.to
+vpnplus.to
// Tabit Technologies Ltd. : https://tabit.cloud/
// Submitted by Oren Agiv <oren@tabit.cloud>
-tabitorder.co.il
-mytabit.co.il
mytabit.com
+mytabit.co.il
+tabitorder.co.il
// TAIFUN Software AG : http://taifun-software.de
// Submitted by Bjoern Henke <dev-server@taifun-software.de>
@@ -15407,11 +15429,11 @@ telebit.io
reservd.com
thingdustdata.com
cust.dev.thingdust.io
+reservd.dev.thingdust.io
cust.disrec.thingdust.io
+reservd.disrec.thingdust.io
cust.prod.thingdust.io
cust.testing.thingdust.io
-reservd.dev.thingdust.io
-reservd.disrec.thingdust.io
reservd.testing.thingdust.io
// ticket i/O GmbH : https://ticket.io
@@ -15473,8 +15495,6 @@ tuxfamily.org
// TwoDNS : https://www.twodns.de/
// Submitted by TwoDNS-Support <support@two-dns.de>
dd-dns.de
-diskstation.eu
-diskstation.org
dray-dns.de
draydns.de
dyn-vpn.de
@@ -15485,6 +15505,8 @@ my-wan.de
syno-ds.de
synology-diskstation.de
synology-ds.de
+diskstation.eu
+diskstation.org
// Typedream : https://typedream.com
// Submitted by Putri Karunia <putri@typedream.com>
@@ -15496,15 +15518,15 @@ pro.typeform.com
// Uberspace : https://uberspace.de
// Submitted by Moritz Werner <mwerner@jonaspasche.com>
-uber.space
*.uberspace.de
+uber.space
// UDR Limited : http://www.udr.hk.com
// Submitted by registry <hostmaster@udr.hk.com>
hk.com
-hk.org
-ltd.hk
inc.hk
+ltd.hk
+hk.org
// UK Intis Telecom LTD : https://it.com
// Submitted by ITComdomains <to@it.com>
@@ -15525,8 +15547,8 @@ org.yt
// United Gameserver GmbH : https://united-gameserver.de
// Submitted by Stefan Schwarz <sysadm@united-gameserver.de>
-virtualuser.de
virtual-user.de
+virtualuser.de
// Upli : https://upli.io
// Submitted by Lenny Bakkalian <lenny.bakkalian@gmail.com>
@@ -15541,6 +15563,11 @@ dnsupdate.info
// Submitted by Ed Moore <Ed.Moore@lib.de.us>
lib.de.us
+// Val Town, Inc : https://val.town/
+// Submitted by Tom MacWright <security@val.town>
+express.val.run
+web.val.run
+
// VeryPositive SIA : http://very.lv
// Submitted by Danko Aleksejevs <danko@very.lv>
2038.io
@@ -15586,10 +15613,10 @@ webflowtest.io
// WebHotelier Technologies Ltd: https://www.webhotelier.net/
// Submitted by Apostolos Tsakpinis <apostolos.tsakpinis@gmail.com>
-reserve-online.net
-reserve-online.com
bookonline.app
hotelwithflight.com
+reserve-online.com
+reserve-online.net
// WebWaddle Ltd: https://webwaddle.com/
// Submitted by Merlin Glander <hostmaster@webwaddle.com>
@@ -15605,21 +15632,33 @@ wedeploy.sh
// Submitted by Jung Jin <jungseok.jin@wdc.com>
remotewd.com
+// Whatbox Inc. : https://whatbox.ca/
+// Submitted by Anthony Ryan <servers@whatbox.ca>
+box.ca
+
// WIARD Enterprises : https://wiardweb.com
// Submitted by Kidd Hustle <kiddhustle@wiardweb.com>
pages.wiardweb.com
// Wikimedia Labs : https://wikitech.wikimedia.org
// Submitted by Arturo Borrero Gonzalez <aborrero@wikimedia.org>
-wmflabs.org
toolforge.org
wmcloud.org
+wmflabs.org
// WISP : https://wisp.gg
// Submitted by Stepan Fedotov <stepan@wisp.gg>
panel.gg
daemon.panel.gg
+// Wix.com, Inc. : https://www.wix.com
+// Submitted by Shahar Talmi / Alon Kochba <publicsuffixlist@wix.com>
+wixsite.com
+wixstudio.com
+editorx.io
+wixstudio.io
+wix.run
+
// Wizard Zines : https://wizardzines.com
// Submitted by Julia Evans <julia@wizardzines.com>
messwithdns.com
@@ -15645,13 +15684,6 @@ weeklylottery.org.uk
wpenginepowered.com
js.wpenginepowered.com
-// Wix.com, Inc. : https://www.wix.com
-// Submitted by Shahar Talmi <shahar@wix.com>
-wixsite.com
-editorx.io
-wixstudio.io
-wix.run
-
// XenonCloud GbR: https://xenoncloud.net
// Submitted by Julian Uphoff <publicsuffixlist@xenoncloud.net>
half.host
@@ -15707,6 +15739,10 @@ za.org
// Submitted by Julian Alker <security@zap-hosting.com>
zap.cloud
+// Zeabur : https://zeabur.com/
+// Submitted by Zeabur Team <contact@zeabur.com>
+zeabur.app
+
// Zine EOOD : https://zine.bg/
// Submitted by Martin Angelov <martin@zine.bg>
bss.design
diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp
index 68a76a0c1f..b688daadc9 100644
--- a/netwerk/dns/nsDNSService2.cpp
+++ b/netwerk/dns/nsDNSService2.cpp
@@ -874,7 +874,7 @@ nsDNSService::Init() {
do_GetService("@mozilla.org/network/oblivious-http-service;1"));
mTrrService = new TRRService();
- if (NS_FAILED(mTrrService->Init())) {
+ if (NS_FAILED(mTrrService->Init(mResolver->IsNativeHTTPSEnabled()))) {
mTrrService = nullptr;
}
@@ -975,6 +975,15 @@ nsresult nsDNSService::PreprocessHostname(bool aLocalDomain,
return NS_OK;
}
+bool nsDNSService::IsLocalDomain(const nsACString& aHostname) const {
+ bool localDomain = mLocalDomains.Contains(aHostname);
+ if (StringEndsWith(aHostname, "."_ns)) {
+ localDomain = localDomain || mLocalDomains.Contains(Substring(
+ aHostname, 0, aHostname.Length() - 1));
+ }
+ return localDomain;
+}
+
nsresult nsDNSService::AsyncResolveInternal(
const nsACString& aHostname, uint16_t type, nsIDNSService::DNSFlags flags,
nsIDNSAdditionalInfo* aInfo, nsIDNSListener* aListener,
@@ -996,7 +1005,8 @@ nsresult nsDNSService::AsyncResolveInternal(
res = mResolver;
idn = mIDN;
- localDomain = mLocalDomains.Contains(aHostname);
+
+ localDomain = IsLocalDomain(aHostname);
}
if (mNotifyResolution) {
@@ -1076,7 +1086,7 @@ nsresult nsDNSService::CancelAsyncResolveInternal(
res = mResolver;
idn = mIDN;
- localDomain = mLocalDomains.Contains(aHostname);
+ localDomain = IsLocalDomain(aHostname);
}
if (!res) {
return NS_ERROR_OFFLINE;
@@ -1212,7 +1222,7 @@ nsresult nsDNSService::ResolveInternal(
MutexAutoLock lock(mLock);
res = mResolver;
idn = mIDN;
- localDomain = mLocalDomains.Contains(aHostname);
+ localDomain = IsLocalDomain(aHostname);
}
if (mNotifyResolution) {
diff --git a/netwerk/dns/nsDNSService2.h b/netwerk/dns/nsDNSService2.h
index 11f22c038e..523abcb613 100644
--- a/netwerk/dns/nsDNSService2.h
+++ b/netwerk/dns/nsDNSService2.h
@@ -83,6 +83,8 @@ class nsDNSService final : public mozilla::net::DNSServiceBase,
nsresult PreprocessHostname(bool aLocalDomain, const nsACString& aInput,
nsIIDNService* aIDN, nsACString& aACE);
+ bool IsLocalDomain(const nsACString& aHostname) const;
+
nsresult AsyncResolveInternal(
const nsACString& aHostname, uint16_t type, nsIDNSService::DNSFlags flags,
nsIDNSAdditionalInfo* aInfo, nsIDNSListener* aListener,
diff --git a/netwerk/dns/nsHostResolver.cpp b/netwerk/dns/nsHostResolver.cpp
index b74b974041..4dcdb3ac79 100644
--- a/netwerk/dns/nsHostResolver.cpp
+++ b/netwerk/dns/nsHostResolver.cpp
@@ -455,7 +455,8 @@ already_AddRefed<nsHostRecord> nsHostResolver::InitLoopbackRecord(
return rec.forget();
}
-static bool IsNativeHTTPSEnabled() {
+// static
+bool nsHostResolver::IsNativeHTTPSEnabled() {
if (!StaticPrefs::network_dns_native_https_query()) {
return false;
}
@@ -527,6 +528,7 @@ nsresult nsHostResolver::ResolveHost(const nsACString& aHost,
bool excludedFromTRR = false;
if (TRRService::Get() && TRRService::Get()->IsExcludedFromTRR(host)) {
flags |= nsIDNSService::RESOLVE_DISABLE_TRR;
+ flags |= nsIDNSService::RESOLVE_DISABLE_NATIVE_HTTPS_QUERY;
excludedFromTRR = true;
if (!aTrrServer.IsEmpty()) {
@@ -1182,8 +1184,14 @@ nsresult nsHostResolver::NameLookup(nsHostRecord* rec,
(rec->mEffectiveTRRMode == nsIRequest::TRR_FIRST_MODE &&
(rec->flags & nsIDNSService::RESOLVE_DISABLE_TRR || serviceNotReady ||
NS_FAILED(rv)))) {
- if (!IsNativeHTTPSEnabled() && !rec->IsAddrRecord()) {
- return rv;
+ if (!rec->IsAddrRecord()) {
+ if (!IsNativeHTTPSEnabled()) {
+ return NS_ERROR_UNKNOWN_HOST;
+ }
+
+ if (rec->flags & nsIDNSService::RESOLVE_DISABLE_NATIVE_HTTPS_QUERY) {
+ return NS_ERROR_UNKNOWN_HOST;
+ }
}
#ifdef DEBUG
diff --git a/netwerk/dns/nsHostResolver.h b/netwerk/dns/nsHostResolver.h
index 02e6a343f8..15ab3a7349 100644
--- a/netwerk/dns/nsHostResolver.h
+++ b/netwerk/dns/nsHostResolver.h
@@ -339,6 +339,8 @@ class nsHostResolver : public nsISupports, public AHostResolver {
* Called by the networking dashboard via the DnsService2
*/
void GetDNSCacheEntries(nsTArray<mozilla::net::DNSCacheEntries>*);
+
+ static bool IsNativeHTTPSEnabled();
};
#endif // nsHostResolver_h__
diff --git a/netwerk/dns/nsIDNSByTypeRecord.idl b/netwerk/dns/nsIDNSByTypeRecord.idl
index 13290e260e..89829c5c2a 100644
--- a/netwerk/dns/nsIDNSByTypeRecord.idl
+++ b/netwerk/dns/nsIDNSByTypeRecord.idl
@@ -32,7 +32,7 @@ native TypeResult(mozilla::net::TypeRecordResultType);
native MaybePort(mozilla::Maybe<uint16_t>);
native MaybeAlpnTuple(mozilla::Maybe<std::tuple<nsCString, mozilla::net::SupportedAlpnRank>>);
-[scriptable, uuid(5d13241b-9d46-448a-90d8-77c418491026)]
+[scriptable, builtinclass, uuid(5d13241b-9d46-448a-90d8-77c418491026)]
interface nsIDNSByTypeRecord : nsIDNSRecord
{
/**
@@ -43,10 +43,10 @@ interface nsIDNSByTypeRecord : nsIDNSRecord
[noscript] readonly attribute TypeResult results;
};
-[scriptable, uuid(2a71750d-cb21-45f1-9e1c-666d18dd7645)]
+[scriptable, builtinclass, uuid(2a71750d-cb21-45f1-9e1c-666d18dd7645)]
interface nsIDNSTXTRecord : nsISupports
{
- CStringArrayRef getRecords();
+ [noscript] CStringArrayRef getRecords();
/*
* Return concatenated strings.
diff --git a/netwerk/dns/nsIDNSRecord.idl b/netwerk/dns/nsIDNSRecord.idl
index 27df2e28be..ebe8869c60 100644
--- a/netwerk/dns/nsIDNSRecord.idl
+++ b/netwerk/dns/nsIDNSRecord.idl
@@ -26,12 +26,12 @@ interface nsINetAddr;
* like an enumerator, allowing the caller to easily step through the
* list of IP addresses.
*/
-[scriptable, uuid(f92228ae-c417-4188-a604-0830a95e7eb9)]
+[scriptable, builtinclass, uuid(f92228ae-c417-4188-a604-0830a95e7eb9)]
interface nsIDNSRecord : nsISupports
{
};
-[scriptable, uuid(cb260e20-943f-4309-953b-78c90d3a7638)]
+[scriptable, builtinclass, uuid(cb260e20-943f-4309-953b-78c90d3a7638)]
interface nsIDNSAddrRecord : nsIDNSRecord
{
/**
diff --git a/netwerk/dns/nsIDNSService.idl b/netwerk/dns/nsIDNSService.idl
index c1aecccd8c..8ceb8f3958 100644
--- a/netwerk/dns/nsIDNSService.idl
+++ b/netwerk/dns/nsIDNSService.idl
@@ -91,9 +91,11 @@ interface nsIDNSService : nsISupports
// If set, the DNS service will pass a DNS record to
// OnLookupComplete even when there was a resolution error.
RESOLVE_WANT_RECORD_ON_ERROR = (1 << 16),
+ // If set, the native HTTPS query is not allowed.
+ RESOLVE_DISABLE_NATIVE_HTTPS_QUERY = (1 << 17),
// Bitflag containing all possible flags.
- ALL_DNSFLAGS_BITS = ((1 << 17) - 1),
+ ALL_DNSFLAGS_BITS = ((1 << 18) - 1),
};
cenum ConfirmationState : 8 {
diff --git a/netwerk/ipc/DocumentLoadListener.h b/netwerk/ipc/DocumentLoadListener.h
index a8e4ffa7ab..6f6ad357ae 100644
--- a/netwerk/ipc/DocumentLoadListener.h
+++ b/netwerk/ipc/DocumentLoadListener.h
@@ -603,7 +603,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
RefPtr<dom::ContentParent> mContentParent;
void RejectOpenPromise(nsresult aStatus, nsresult aLoadGroupStatus,
- bool aContinueNavigating, const char* aLocation) {
+ bool aContinueNavigating, StaticString aLocation) {
// It is possible for mOpenPromise to not be set if AsyncOpen failed and
// the DocumentChannel got canceled.
if (!mOpenPromiseResolved && mOpenPromise) {
diff --git a/netwerk/locales/en-US/necko.properties b/netwerk/locales/en-US/necko.properties
index 7498cca20b..14d16f73a9 100644
--- a/netwerk/locales/en-US/necko.properties
+++ b/netwerk/locales/en-US/necko.properties
@@ -70,6 +70,8 @@ CookiePathOversize=Cookie “%1$S” is invalid because its path size is too big
CookieRejectedByPermissionManager=Cookie “%1$S” has been rejected by user set permissions.
# LOCALIZATION NOTE (CookieRejectedInvalidCharName): %1$S is the cookie name.
CookieRejectedInvalidCharName=Cookie “%1$S” has been rejected for invalid characters in the name.
+# LOCALIZATION NOTE (CookieRejectedInvalidCharAttributes): %1$S is the cookie name.
+CookieRejectedInvalidCharAttributes=Cookie “%1$S” has been rejected for invalid characters in the attributes.
# LOCALIZATION NOTE (CookieRejectedInvalidDomain): %1$S is the cookie name.
CookieRejectedInvalidDomain=Cookie “%1$S” has been rejected for invalid domain.
# LOCALIZATION NOTE (CookieRejectedInvalidPrefix): %1$S is the cookie name.
diff --git a/netwerk/metrics.yaml b/netwerk/metrics.yaml
index 648dced01e..c14b8f2288 100644
--- a/netwerk/metrics.yaml
+++ b/netwerk/metrics.yaml
@@ -104,14 +104,16 @@ networking:
unit: integer
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942#TDB
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_sensitivity:
- technical
notification_emails:
- necko@mozilla.com
- edgul@mozilla.com
- expires: 128
+ expires: 134
cookie_count_partitioned:
type: custom_distribution
@@ -124,14 +126,16 @@ networking:
unit: integer
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942#TDB
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_sensitivity:
- technical
notification_emails:
- necko@mozilla.com
- edgul@mozilla.com
- expires: 128
+ expires: 134
cookie_count_unpartitioned:
type: custom_distribution
@@ -144,14 +148,16 @@ networking:
unit: integer
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942#TDB
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_sensitivity:
- technical
notification_emails:
- necko@mozilla.com
- edgul@mozilla.com
- expires: 128
+ expires: 134
cookie_count_part_by_key:
type: custom_distribution
@@ -165,14 +171,16 @@ networking:
unit: integer
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942#TDB
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_sensitivity:
- technical
notification_emails:
- necko@mozilla.com
- edgul@mozilla.com
- expires: 128
+ expires: 134
cookie_count_unpart_by_key:
type: custom_distribution
@@ -186,14 +194,16 @@ networking:
unit: integer
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942#TDB
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_sensitivity:
- technical
notification_emails:
- necko@mozilla.com
- edgul@mozilla.com
- expires: 128
+ expires: 134
cookie_purge_max:
type: custom_distribution
@@ -208,14 +218,16 @@ networking:
unit: integer
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942#TDB
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_sensitivity:
- technical
notification_emails:
- necko@mozilla.com
- edgul@mozilla.com
- expires: 128
+ expires: 134
cookie_purge_entry_max:
type: custom_distribution
@@ -230,14 +242,16 @@ networking:
unit: integer
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828942#TDB
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1892158
data_sensitivity:
- technical
notification_emails:
- necko@mozilla.com
- edgul@mozilla.com
- expires: 128
+ expires: 134
set_cookie:
type: counter
@@ -368,6 +382,22 @@ networking:
expires: never
telemetry_mirror: DNS_FAILED_LOOKUP_TIME
+ dns_native_https_call_time:
+ type: timing_distribution
+ time_unit: millisecond
+ description: >
+ Time spent in the call to the native OS DNS resolution.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1885529
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1885529
+ data_sensitivity:
+ - technical
+ notification_emails:
+ - necko@mozilla.com
+ - vgosu@mozilla.com
+ expires: never
+
dns_native_count:
type: labeled_counter
description: >
diff --git a/netwerk/protocol/about/nsAboutProtocolHandler.cpp b/netwerk/protocol/about/nsAboutProtocolHandler.cpp
index 5bbaa9010e..ab4d62f989 100644
--- a/netwerk/protocol/about/nsAboutProtocolHandler.cpp
+++ b/netwerk/protocol/about/nsAboutProtocolHandler.cpp
@@ -21,6 +21,7 @@
#include "nsIChannel.h"
#include "nsIScriptError.h"
#include "nsIClassInfoImpl.h"
+#include "DefaultURI.h"
#include "mozilla/ipc/URIUtils.h"
@@ -136,6 +137,16 @@ nsresult nsAboutProtocolHandler::CreateNewURI(const nsACString& aSpec,
NS_ENSURE_SUCCESS(rv, rv);
}
+ // use DefaultURI to check for validity when we have possible hostnames
+ // since nsSimpleURI doesn't know about hostnames
+ auto pos = aSpec.Find("about:/");
+ if (pos != kNotFound) {
+ rv = NS_MutateURI(new mozilla::net::DefaultURI::Mutator())
+ .SetSpec(aSpec)
+ .Finalize(url);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
url.swap(*aResult);
return NS_OK;
}
diff --git a/netwerk/protocol/data/nsDataHandler.cpp b/netwerk/protocol/data/nsDataHandler.cpp
index adb86bf484..e9a72cd9ed 100644
--- a/netwerk/protocol/data/nsDataHandler.cpp
+++ b/netwerk/protocol/data/nsDataHandler.cpp
@@ -68,16 +68,12 @@ nsDataHandler::GetScheme(nsACString& result) {
// use DefaultURI to check for validity when we have possible hostnames
// since nsSimpleURI doesn't know about hostnames
- auto pos = aSpec.Find("data:");
+ auto pos = aSpec.Find("data:/");
if (pos != kNotFound) {
- nsDependentCSubstring rest(aSpec, pos + sizeof("data:") - 1, -1);
- if (StringBeginsWith(rest, "//"_ns)) {
- nsCOMPtr<nsIURI> uriWithHost;
- rv = NS_MutateURI(new mozilla::net::DefaultURI::Mutator())
- .SetSpec(aSpec)
- .Finalize(uriWithHost);
- NS_ENSURE_SUCCESS(rv, rv);
- }
+ rv = NS_MutateURI(new mozilla::net::DefaultURI::Mutator())
+ .SetSpec(aSpec)
+ .Finalize(uri);
+ NS_ENSURE_SUCCESS(rv, rv);
}
uri.forget(result);
diff --git a/netwerk/protocol/http/ConnectionEntry.cpp b/netwerk/protocol/http/ConnectionEntry.cpp
index dc0dfd103c..36ebba5ec3 100644
--- a/netwerk/protocol/http/ConnectionEntry.cpp
+++ b/netwerk/protocol/http/ConnectionEntry.cpp
@@ -509,6 +509,9 @@ void ConnectionEntry::VerifyTraffic() {
mActiveConns.RemoveElementAt(index);
gHttpHandler->ConnMgr()->DecrementActiveConnCount(conn);
mPendingConns.AppendElement(conn);
+ // After DontReuse(), the connection will be closed after the last
+ // transition is done.
+ conn->DontReuse();
LOG(("Move active connection to pending list [conn=%p]\n",
conn.get()));
}
diff --git a/netwerk/protocol/http/Http3WebTransportSession.cpp b/netwerk/protocol/http/Http3WebTransportSession.cpp
index 9ef4da70c0..cee1fd75fd 100644
--- a/netwerk/protocol/http/Http3WebTransportSession.cpp
+++ b/netwerk/protocol/http/Http3WebTransportSession.cpp
@@ -447,7 +447,10 @@ Http3WebTransportSession::OnIncomingWebTransportStream(
return nullptr;
}
- mListener->OnIncomingStreamAvailableInternal(stream);
+ if (nsCOMPtr<WebTransportSessionEventListenerInternal> listener =
+ do_QueryInterface(mListener)) {
+ listener->OnIncomingStreamAvailableInternal(stream);
+ }
return stream.forget();
}
@@ -470,7 +473,10 @@ void Http3WebTransportSession::OnDatagramReceived(nsTArray<uint8_t>&& aData) {
return;
}
- mListener->OnDatagramReceivedInternal(std::move(aData));
+ if (nsCOMPtr<WebTransportSessionEventListenerInternal> listener =
+ do_QueryInterface(mListener)) {
+ listener->OnDatagramReceivedInternal(std::move(aData));
+ }
}
void Http3WebTransportSession::GetMaxDatagramSize() {
diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp
index ff88b02753..8483bb6144 100644
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -1319,8 +1319,6 @@ void HttpBaseChannel::ExplicitSetUploadStreamLength(
return;
}
- // SetRequestHeader propagates headers to chrome if HttpChannelChild
- MOZ_ASSERT(!LoadWasOpened());
nsAutoCString contentLengthStr;
contentLengthStr.AppendInt(aContentLength);
SetRequestHeader(header, contentLengthStr, false);
@@ -2298,6 +2296,19 @@ HttpBaseChannel::UpgradeToSecure() {
}
NS_IMETHODIMP
+HttpBaseChannel::GetRequestObserversCalled(bool* aCalled) {
+ NS_ENSURE_ARG_POINTER(aCalled);
+ *aCalled = LoadRequestObserversCalled();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::SetRequestObserversCalled(bool aCalled) {
+ StoreRequestObserversCalled(aCalled);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
HttpBaseChannel::GetRequestContextID(uint64_t* aRCID) {
NS_ENSURE_ARG_POINTER(aRCID);
*aRCID = mRequestContextID;
diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h
index d6d693212b..3a2c6192d1 100644
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -228,6 +228,8 @@ class HttpBaseChannel : public nsHashPropertyBag,
NS_IMETHOD GetRequestSucceeded(bool* aValue) override;
NS_IMETHOD RedirectTo(nsIURI* newURI) override;
NS_IMETHOD UpgradeToSecure() override;
+ NS_IMETHOD GetRequestObserversCalled(bool* aCalled) override;
+ NS_IMETHOD SetRequestObserversCalled(bool aCalled) override;
NS_IMETHOD GetRequestContextID(uint64_t* aRCID) override;
NS_IMETHOD GetTransferSize(uint64_t* aTransferSize) override;
NS_IMETHOD GetRequestSize(uint64_t* aRequestSize) override;
@@ -690,6 +692,9 @@ class HttpBaseChannel : public nsHashPropertyBag,
void SetChannelBlockedByOpaqueResponse();
bool Http3Allowed() const;
+ virtual void ExplicitSetUploadStreamLength(uint64_t aContentLength,
+ bool aSetContentLengthHeader);
+
friend class OpaqueResponseBlocker;
friend class PrivateBrowsingChannel<HttpBaseChannel>;
friend class InterceptFailedOnStop;
@@ -721,9 +726,6 @@ class HttpBaseChannel : public nsHashPropertyBag,
// Proxy release all members above on main thread.
void ReleaseMainThreadOnlyReferences();
- void ExplicitSetUploadStreamLength(uint64_t aContentLength,
- bool aSetContentLengthHeader);
-
void MaybeResumeAsyncOpen();
protected:
diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp
index 8b581b070e..97c80b046a 100644
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -3418,4 +3418,12 @@ NS_IMETHODIMP HttpChannelChild::SetWebTransportSessionEventListener(
return NS_OK;
}
+void HttpChannelChild::ExplicitSetUploadStreamLength(
+ uint64_t aContentLength, bool aSetContentLengthHeader) {
+ // SetRequestHeader propagates headers to chrome if HttpChannelChild
+ MOZ_ASSERT(!LoadWasOpened());
+ HttpBaseChannel::ExplicitSetUploadStreamLength(aContentLength,
+ aSetContentLengthHeader);
+}
+
} // namespace mozilla::net
diff --git a/netwerk/protocol/http/HttpChannelChild.h b/netwerk/protocol/http/HttpChannelChild.h
index 8cfc820a23..190b195aaa 100644
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -187,6 +187,9 @@ class HttpChannelChild final : public PHttpChannelChild,
const nsAString& aURL,
const nsAString& aContentType) override;
+ virtual void ExplicitSetUploadStreamLength(
+ uint64_t aContentLength, bool aSetContentLengthHeader) override;
+
private:
// We want to handle failure result of AsyncOpen, hence AsyncOpen calls the
// Internal method
diff --git a/netwerk/protocol/http/NullHttpChannel.cpp b/netwerk/protocol/http/NullHttpChannel.cpp
index eae11441af..8916c8a48e 100644
--- a/netwerk/protocol/http/NullHttpChannel.cpp
+++ b/netwerk/protocol/http/NullHttpChannel.cpp
@@ -247,6 +247,16 @@ NS_IMETHODIMP
NullHttpChannel::UpgradeToSecure() { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHODIMP
+NullHttpChannel::GetRequestObserversCalled(bool* aCalled) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+NullHttpChannel::SetRequestObserversCalled(bool aCalled) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
NullHttpChannel::GetRequestContextID(uint64_t* _retval) {
return NS_ERROR_NOT_IMPLEMENTED;
}
diff --git a/netwerk/protocol/http/ObliviousHttpChannel.cpp b/netwerk/protocol/http/ObliviousHttpChannel.cpp
index 1b4449f004..99b1def6d5 100644
--- a/netwerk/protocol/http/ObliviousHttpChannel.cpp
+++ b/netwerk/protocol/http/ObliviousHttpChannel.cpp
@@ -351,6 +351,16 @@ ObliviousHttpChannel::UpgradeToSecure() {
}
NS_IMETHODIMP
+ObliviousHttpChannel::GetRequestObserversCalled(bool* aCalled) {
+ return mInnerChannel->GetRequestObserversCalled(aCalled);
+}
+
+NS_IMETHODIMP
+ObliviousHttpChannel::SetRequestObserversCalled(bool aCalled) {
+ return mInnerChannel->SetRequestObserversCalled(aCalled);
+}
+
+NS_IMETHODIMP
ObliviousHttpChannel::GetRequestContextID(uint64_t* _retval) {
return mInnerChannel->GetRequestContextID(_retval);
}
diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp
index 4428b72426..c5e6deb241 100644
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -637,6 +637,32 @@ nsresult nsHttpChannel::OnBeforeConnect() {
return MaybeUseHTTPSRRForUpgrade(shouldUpgrade, NS_OK);
}
+// Returns true if the network connectivity checker indicated
+// that HTTPS records can be resolved on this network - false otherwise.
+// When TRR is enabled, we always return true, as resolving HTTPS
+// records don't depend on the network.
+static bool canUseHTTPSRRonNetwork() {
+ if (nsCOMPtr<nsIDNSService> dns = mozilla::components::DNS::Service()) {
+ nsIDNSService::ResolverMode mode;
+ // If the browser is currently using TRR/DoH, then it can
+ // definitely resolve HTTPS records.
+ if (NS_SUCCEEDED(dns->GetCurrentTrrMode(&mode)) &&
+ (mode == nsIDNSService::MODE_TRRFIRST ||
+ mode == nsIDNSService::MODE_TRRONLY)) {
+ return true;
+ }
+ }
+ if (RefPtr<NetworkConnectivityService> ncs =
+ NetworkConnectivityService::GetSingleton()) {
+ nsINetworkConnectivityService::ConnectivityState state;
+ if (NS_SUCCEEDED(ncs->GetDNS_HTTPS(&state)) &&
+ state == nsINetworkConnectivityService::NOT_AVAILABLE) {
+ return false;
+ }
+ }
+ return true;
+}
+
nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade,
nsresult aStatus) {
if (NS_FAILED(aStatus)) {
@@ -657,6 +683,13 @@ nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade,
return true;
}
+ // If the network connectivity checker indicates the network is
+ // blocking HTTPS requests, then we should skip them so we don't
+ // needlessly wait for a timeout.
+ if (!canUseHTTPSRRonNetwork()) {
+ return true;
+ }
+
nsAutoCString uriHost;
mURI->GetAsciiHost(uriHost);
@@ -1022,11 +1055,22 @@ nsresult nsHttpChannel::DoConnectActual(
LOG(("nsHttpChannel::DoConnectActual [this=%p, aTransWithStickyConn=%p]\n",
this, aTransWithStickyConn));
- nsresult rv = SetupTransaction();
+ nsresult rv = SetupChannelForTransaction();
if (NS_FAILED(rv)) {
return rv;
}
+ return DispatchTransaction(aTransWithStickyConn);
+}
+
+nsresult nsHttpChannel::DispatchTransaction(
+ HttpTransactionShell* aTransWithStickyConn) {
+ LOG(("nsHttpChannel::DispatchTransaction [this=%p, aTransWithStickyConn=%p]",
+ this, aTransWithStickyConn));
+ nsresult rv = InitTransaction();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
if (aTransWithStickyConn) {
rv = gHttpHandler->InitiateTransactionWithStickyConn(
mTransaction, mPriority, aTransWithStickyConn);
@@ -1212,10 +1256,11 @@ void nsHttpChannel::HandleAsyncNotModified() {
if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus);
}
-nsresult nsHttpChannel::SetupTransaction() {
- LOG(("nsHttpChannel::SetupTransaction [this=%p, cos=%lu, inc=%d prio=%d]\n",
- this, mClassOfService.Flags(), mClassOfService.Incremental(),
- mPriority));
+nsresult nsHttpChannel::SetupChannelForTransaction() {
+ LOG((
+ "nsHttpChannel::SetupChannelForTransaction [this=%p, cos=%lu, inc=%d "
+ "prio=%d]\n",
+ this, mClassOfService.Flags(), mClassOfService.Incremental(), mPriority));
NS_ENSURE_TRUE(!mTransaction, NS_ERROR_ALREADY_INITIALIZED);
@@ -1340,24 +1385,37 @@ nsresult nsHttpChannel::SetupTransaction() {
// We need to send 'Pragma:no-cache' to inhibit proxy caching even if
// no proxy is configured since we might be talking with a transparent
// proxy, i.e. one that operates at the network level. See bug #14772.
- rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
+ // But we should not touch Pragma if Cache-Control is already set
+ // (https://fetch.spec.whatwg.org/#ref-for-concept-request-cache-mode%E2%91%A3)
+ if (!mRequestHead.HasHeader(nsHttp::Pragma)) {
+ rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+ }
// If we're configured to speak HTTP/1.1 then also send 'Cache-control:
- // no-cache'
- if (mRequestHead.Version() >= HttpVersion::v1_1) {
+ // no-cache'. But likewise don't touch Cache-Control if it's already set.
+ if (mRequestHead.Version() >= HttpVersion::v1_1 &&
+ !mRequestHead.HasHeader(nsHttp::Cache_Control)) {
rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "no-cache", true);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
- } else if ((mLoadFlags & VALIDATE_ALWAYS) && !LoadCacheEntryIsWriteOnly()) {
+ } else if (mLoadFlags & VALIDATE_ALWAYS) {
// We need to send 'Cache-Control: max-age=0' to force each cache along
// the path to the origin server to revalidate its own entry, if any,
// with the next cache or server. See bug #84847.
//
// If we're configured to speak HTTP/1.0 then just send 'Pragma: no-cache'
+ //
+ // But don't send the headers if they're already set:
+ // https://fetch.spec.whatwg.org/#ref-for-concept-request-cache-mode%E2%91%A2
if (mRequestHead.Version() >= HttpVersion::v1_1) {
- rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "max-age=0", true);
+ if (!mRequestHead.HasHeader(nsHttp::Cache_Control)) {
+ rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "max-age=0",
+ true);
+ }
} else {
- rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
+ if (!mRequestHead.HasHeader(nsHttp::Pragma)) {
+ rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
+ }
}
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
@@ -1395,6 +1453,30 @@ nsresult nsHttpChannel::SetupTransaction() {
}
}
+ // See bug #466080. Transfer LOAD_ANONYMOUS flag to socket-layer.
+ if (mLoadFlags & LOAD_ANONYMOUS) mCaps |= NS_HTTP_LOAD_ANONYMOUS;
+
+ if (LoadTimingEnabled()) mCaps |= NS_HTTP_TIMING_ENABLED;
+
+ if (mUpgradeProtocolCallback) {
+ rv = mRequestHead.SetHeader(nsHttp::Upgrade, mUpgradeProtocol, false);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+ rv = mRequestHead.SetHeaderOnce(nsHttp::Connection, nsHttp::Upgrade.get(),
+ true);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+ mCaps |= NS_HTTP_STICKY_CONNECTION;
+ mCaps &= ~NS_HTTP_ALLOW_KEEPALIVE;
+ }
+
+ if (mWebTransportSessionEventListener) {
+ mCaps |= NS_HTTP_STICKY_CONNECTION;
+ }
+
+ return NS_OK;
+}
+
+nsresult nsHttpChannel::InitTransaction() {
+ nsresult rv;
// create wrapper for this channel's notification callbacks
nsCOMPtr<nsIInterfaceRequestor> callbacks;
NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
@@ -1445,25 +1527,6 @@ nsresult nsHttpChannel::SetupTransaction() {
// nsIHttpActivityObserver.
gHttpHandler->AddHttpChannel(mChannelId, ToSupports(this));
- // See bug #466080. Transfer LOAD_ANONYMOUS flag to socket-layer.
- if (mLoadFlags & LOAD_ANONYMOUS) mCaps |= NS_HTTP_LOAD_ANONYMOUS;
-
- if (LoadTimingEnabled()) mCaps |= NS_HTTP_TIMING_ENABLED;
-
- if (mUpgradeProtocolCallback) {
- rv = mRequestHead.SetHeader(nsHttp::Upgrade, mUpgradeProtocol, false);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- rv = mRequestHead.SetHeaderOnce(nsHttp::Connection, nsHttp::Upgrade.get(),
- true);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- mCaps |= NS_HTTP_STICKY_CONNECTION;
- mCaps &= ~NS_HTTP_ALLOW_KEEPALIVE;
- }
-
- if (mWebTransportSessionEventListener) {
- mCaps |= NS_HTTP_STICKY_CONNECTION;
- }
-
nsCOMPtr<nsIHttpPushListener> pushListener;
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
NS_GET_IID(nsIHttpPushListener),
@@ -6566,7 +6629,7 @@ nsresult nsHttpChannel::BeginConnect() {
!(mLoadInfo->TriggeringPrincipal()->IsSystemPrincipal() &&
mLoadInfo->GetExternalContentPolicyType() !=
ExtContentPolicy::TYPE_DOCUMENT) &&
- !mConnectionInfo->UsingConnect();
+ !mConnectionInfo->UsingConnect() && canUseHTTPSRRonNetwork();
if (!httpsRRAllowed) {
mCaps |= NS_HTTP_DISALLOW_HTTPS_RR;
}
@@ -6611,8 +6674,10 @@ nsresult nsHttpChannel::BeginConnect() {
Unused << gHttpHandler->AddConnectionHeader(&mRequestHead, mCaps);
if (!LoadIsTRRServiceChannel() &&
- (mLoadFlags & VALIDATE_ALWAYS ||
- BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass()))) {
+ ((mLoadFlags & LOAD_FRESH_CONNECTION) ||
+ (!StaticPrefs::network_dns_only_refresh_on_fresh_connection() &&
+ (mLoadFlags & VALIDATE_ALWAYS ||
+ BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass()))))) {
mCaps |= NS_HTTP_REFRESH_DNS;
}
@@ -6753,7 +6818,7 @@ nsresult nsHttpChannel::MaybeStartDNSPrefetch() {
}
if (gHttpHandler->UseHTTPSRRAsAltSvcEnabled() && !mHTTPSSVCRecord &&
- !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR)) {
+ !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR) && canUseHTTPSRRonNetwork()) {
MOZ_ASSERT(!mHTTPSSVCRecord);
OriginAttributes originAttributes;
diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h
index e2fb5abde9..78dac11a4d 100644
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -335,7 +335,10 @@ class nsHttpChannel final : public HttpBaseChannel,
void OnHTTPSRRAvailable(nsIDNSHTTPSSVCRecord* aRecord);
[[nodiscard]] nsresult Connect();
void SpeculativeConnect();
- [[nodiscard]] nsresult SetupTransaction();
+ [[nodiscard]] nsresult SetupChannelForTransaction();
+ [[nodiscard]] nsresult InitTransaction();
+ [[nodiscard]] nsresult DispatchTransaction(
+ HttpTransactionShell* aTransWithStickyConn);
[[nodiscard]] nsresult CallOnStartRequest();
[[nodiscard]] nsresult ProcessResponse();
void AsyncContinueProcessResponse();
diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp
index cd41cd65bc..54e1d25557 100644
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -895,14 +895,6 @@ bool nsHttpConnection::IsAlive() {
nsresult rv = mSocketTransport->IsAlive(&alive);
if (NS_FAILED(rv)) alive = false;
-// #define TEST_RESTART_LOGIC
-#ifdef TEST_RESTART_LOGIC
- if (!alive) {
- LOG(("pretending socket is still alive to test restart logic\n"));
- alive = true;
- }
-#endif
-
return alive;
}
diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
index dbbd8fe0ca..28e2f3f07c 100644
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -62,16 +62,23 @@ struct UrlMarker {
}
static void StreamJSONMarkerData(
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
- const mozilla::ProfilerString8View& aURL) {
+ const mozilla::ProfilerString8View& aURL, const TimeDuration& aDuration,
+ uint64_t aChannelId) {
if (aURL.Length() != 0) {
aWriter.StringProperty("url", aURL);
}
+ if (!aDuration.IsZero()) {
+ aWriter.DoubleProperty("duration", aDuration.ToMilliseconds());
+ }
+ aWriter.IntProperty("channelId", static_cast<int64_t>(aChannelId));
}
static MarkerSchema MarkerTypeDisplay() {
using MS = MarkerSchema;
MS schema(MS::Location::MarkerChart, MS::Location::MarkerTable);
schema.SetTableLabel("{marker.name} - {marker.data.url}");
- schema.AddKeyFormat("url", MS::Format::Url);
+ schema.AddKeyFormatSearchable("url", MS::Format::Url,
+ MS::Searchable::Searchable);
+ schema.AddKeyLabelFormat("duration", "Duration", MS::Format::Duration);
return schema;
}
};
@@ -505,9 +512,10 @@ nsresult nsHttpConnectionMgr::SpeculativeConnect(
return NS_OK;
}
- nsCString url = ci->EndToEndSSL() ? "https://"_ns : "http://"_ns;
+ nsAutoCString url(ci->EndToEndSSL() ? "https://"_ns : "http://"_ns);
url += ci->GetOrigin();
- PROFILER_MARKER("SpeculativeConnect", NETWORK, {}, UrlMarker, url);
+ PROFILER_MARKER("SpeculativeConnect", NETWORK, {}, UrlMarker, url,
+ TimeDuration::Zero(), 0);
RefPtr<SpeculativeConnectArgs> args = new SpeculativeConnectArgs();
@@ -800,6 +808,11 @@ HttpConnectionBase* nsHttpConnectionMgr::FindCoalescableConnection(
MOZ_ASSERT(ent->mConnInfo);
nsHttpConnectionInfo* ci = ent->mConnInfo;
LOG(("FindCoalescableConnection %s\n", ci->HashKey().get()));
+
+ if (ci->GetWebTransport()) {
+ LOG(("Don't coalesce a WebTransport conn "));
+ return nullptr;
+ }
// First try and look it up by origin frame
nsCString newKey;
BuildOriginFrameHashKey(newKey, ci, ci->GetOrigin(), ci->OriginPort());
@@ -1649,9 +1662,9 @@ nsresult nsHttpConnectionMgr::DispatchTransaction(ConnectionEntry* ent,
trans->CancelPacing(NS_OK);
TimeStamp now = TimeStamp::Now();
+ TimeDuration elapsed = now - trans->GetPendingTime();
auto recordPendingTimeForHTTPSRR = [&](nsCString& aKey) {
uint32_t stage = trans->HTTPSSVCReceivedStage();
- TimeDuration elapsed = now - trans->GetPendingTime();
if (HTTPS_RR_IS_USED(stage)) {
glean::networking::transaction_wait_time_https_rr.AccumulateRawDuration(
elapsed);
@@ -1659,10 +1672,16 @@ nsresult nsHttpConnectionMgr::DispatchTransaction(ConnectionEntry* ent,
} else {
glean::networking::transaction_wait_time.AccumulateRawDuration(elapsed);
}
- PerfStats::RecordMeasurement(PerfStats::Metric::HttpTransactionWaitTime,
- elapsed);
};
+ PerfStats::RecordMeasurement(PerfStats::Metric::HttpTransactionWaitTime,
+ elapsed);
+
+ PROFILER_MARKER(
+ "DispatchTransaction", NETWORK,
+ MarkerOptions(MarkerTiming::Interval(trans->GetPendingTime(), now)),
+ UrlMarker, trans->GetUrl(), elapsed, trans->ChannelId());
+
nsAutoCString httpVersionkey("h1"_ns);
if (conn->UsingSpdy() || conn->UsingHttp3()) {
LOG(
@@ -1770,6 +1789,9 @@ nsresult nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction* trans) {
trans->SetPendingTime();
+ PROFILER_MARKER("ProcessNewTransaction", NETWORK, {}, UrlMarker,
+ trans->GetUrl(), TimeDuration::Zero(), trans->ChannelId());
+
RefPtr<Http2PushedStreamWrapper> pushedStreamWrapper =
trans->GetPushedStream();
if (pushedStreamWrapper) {
diff --git a/netwerk/protocol/http/nsHttpHandler.cpp b/netwerk/protocol/http/nsHttpHandler.cpp
index b6440c88b5..d0aebdf965 100644
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -2204,12 +2204,8 @@ nsresult nsHttpHandler::SpeculativeConnectInternal(
originAttributes = std::move(aOriginAttributes.ref());
} else if (aPrincipal) {
originAttributes = aPrincipal->OriginAttributesRef();
- StoragePrincipalHelper::UpdateOriginAttributesForNetworkState(
- aURI, originAttributes);
} else if (loadContext) {
loadContext->GetOriginAttributes(originAttributes);
- StoragePrincipalHelper::UpdateOriginAttributesForNetworkState(
- aURI, originAttributes);
}
nsCOMPtr<nsIURI> clone;
@@ -2222,6 +2218,15 @@ nsresult nsHttpHandler::SpeculativeConnectInternal(
}
}
+ if (!aOriginAttributes) {
+ // We must update the originAttributes with the network state first party
+ // domain **after** we upgrade aURI to https.
+ // Otherwise the speculative connection will be keyed by a http URL
+ // and end up not being used.
+ StoragePrincipalHelper::UpdateOriginAttributesForNetworkState(
+ aURI, originAttributes);
+ }
+
nsAutoCString scheme;
nsresult rv = aURI->GetScheme(scheme);
if (NS_FAILED(rv)) return rv;
@@ -2748,12 +2753,15 @@ bool nsHttpHandler::UseHTTPSRRAsAltSvcEnabled() const {
}
bool nsHttpHandler::EchConfigEnabled(bool aIsHttp3) const {
+ if (mParentalControlEnabled) {
+ return false;
+ }
+
if (!aIsHttp3) {
return StaticPrefs::network_dns_echconfig_enabled();
}
- return StaticPrefs::network_dns_echconfig_enabled() &&
- StaticPrefs::network_dns_http3_echconfig_enabled();
+ return StaticPrefs::network_dns_http3_echconfig_enabled();
}
bool nsHttpHandler::FallbackToOriginIfConfigsAreECHAndAllFailed() const {
diff --git a/netwerk/protocol/http/nsHttpTransaction.cpp b/netwerk/protocol/http/nsHttpTransaction.cpp
index 24ef50fb85..545dd5a142 100644
--- a/netwerk/protocol/http/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -398,11 +398,16 @@ nsresult nsHttpTransaction::Init(
}
RefPtr<nsHttpChannel> httpChannel = do_QueryObject(eventsink);
- RefPtr<WebTransportSessionEventListener> listener =
- httpChannel ? httpChannel->GetWebTransportSessionEventListener()
- : nullptr;
- if (listener) {
- mWebTransportSessionEventListener = std::move(listener);
+ if (httpChannel) {
+ RefPtr<WebTransportSessionEventListener> listener =
+ httpChannel->GetWebTransportSessionEventListener();
+ if (listener) {
+ mWebTransportSessionEventListener = std::move(listener);
+ }
+ nsCOMPtr<nsIURI> uri;
+ if (NS_SUCCEEDED(httpChannel->GetURI(getter_AddRefs(uri)))) {
+ mUrl = uri->GetSpecOrDefault();
+ }
}
return NS_OK;
@@ -2198,8 +2203,9 @@ bool nsHttpTransaction::HandleWebTransportResponse(uint16_t aStatus) {
webTransportListener = mWebTransportSessionEventListener;
mWebTransportSessionEventListener = nullptr;
}
- if (webTransportListener) {
- webTransportListener->OnSessionReadyInternal(wtSession);
+ if (nsCOMPtr<WebTransportSessionEventListenerInternal> listener =
+ do_QueryInterface(webTransportListener)) {
+ listener->OnSessionReadyInternal(wtSession);
wtSession->SetWebTransportSessionEventListener(webTransportListener);
}
@@ -3289,7 +3295,9 @@ nsresult nsHttpTransaction::OnHTTPSRRAvailable(
RefPtr<nsHttpConnectionInfo> newInfo =
mConnInfo->CloneAndAdoptHTTPSSVCRecord(svcbRecord);
- bool needFastFallback = newInfo->IsHttp3();
+ // Don't fallback until we support WebTransport over HTTP/2.
+ // TODO: implement fallback in bug 1874102.
+ bool needFastFallback = newInfo->IsHttp3() && !newInfo->GetWebTransport();
bool foundInPendingQ = gHttpHandler->ConnMgr()->RemoveTransFromConnEntry(
this, mHashKeyOfConnectionEntry);
diff --git a/netwerk/protocol/http/nsHttpTransaction.h b/netwerk/protocol/http/nsHttpTransaction.h
index 5256de4cf2..dd019e00e8 100644
--- a/netwerk/protocol/http/nsHttpTransaction.h
+++ b/netwerk/protocol/http/nsHttpTransaction.h
@@ -196,6 +196,10 @@ class nsHttpTransaction final : public nsAHttpTransaction,
bool IsForWebTransport() { return mIsForWebTransport; }
+ nsAutoCString GetUrl() { return mUrl; }
+
+ uint64_t ChannelId() { return mChannelId; }
+
private:
friend class DeleteHttpTransaction;
virtual ~nsHttpTransaction();
@@ -593,6 +597,8 @@ class nsHttpTransaction final : public nsAHttpTransaction,
nsCString mHashKeyOfConnectionEntry;
nsCOMPtr<WebTransportSessionEventListener> mWebTransportSessionEventListener;
+
+ nsAutoCString mUrl;
};
} // namespace mozilla::net
diff --git a/netwerk/protocol/http/nsIHttpChannel.idl b/netwerk/protocol/http/nsIHttpChannel.idl
index 1bd7aeba37..a8372ba080 100644
--- a/netwerk/protocol/http/nsIHttpChannel.idl
+++ b/netwerk/protocol/http/nsIHttpChannel.idl
@@ -494,4 +494,12 @@ interface nsIHttpChannel : nsIIdentChannel
[must_use] attribute AString classicScriptHintCharset;
[must_use] attribute AString documentCharacterSet;
+
+ /**
+ * Update the requestObserversCalled boolean flag.
+ *
+ * Used by WebDriver BiDi network interception to modify properties of the
+ * request such as `method` or `body` as late as possible.
+ */
+ [must_use] attribute boolean requestObserversCalled;
};
diff --git a/netwerk/protocol/http/nsIHttpChannelInternal.idl b/netwerk/protocol/http/nsIHttpChannelInternal.idl
index 64f41be28b..620718f4bb 100644
--- a/netwerk/protocol/http/nsIHttpChannelInternal.idl
+++ b/netwerk/protocol/http/nsIHttpChannelInternal.idl
@@ -56,7 +56,7 @@ interface nsIHttpUpgradeListener : nsISupports
[must_use] void onUpgradeFailed(in nsresult aErrorCode);
- void onWebSocketConnectionAvailable(in WebSocketConnectionBase aConnection);
+ [noscript] void onWebSocketConnectionAvailable(in WebSocketConnectionBase aConnection);
};
/**
diff --git a/netwerk/protocol/res/SubstitutingProtocolHandler.cpp b/netwerk/protocol/res/SubstitutingProtocolHandler.cpp
index 523aaa435d..a7d87b9fb2 100644
--- a/netwerk/protocol/res/SubstitutingProtocolHandler.cpp
+++ b/netwerk/protocol/res/SubstitutingProtocolHandler.cpp
@@ -437,7 +437,7 @@ nsresult SubstitutingProtocolHandler::NewURI(const nsACString& aSpec,
// "android" is the only root that would return the RESOLVE_JAR_URI flag
// see nsResProtocolHandler::GetSubstitutionInternal
- if (MustResolveJAR(host)) {
+ if (GetJARFlags(host) & nsISubstitutingProtocolHandler::RESOLVE_JAR_URI) {
return ResolveJARURI(uri, aResult);
}
@@ -599,8 +599,7 @@ nsresult SubstitutingProtocolHandler::GetSubstitution(
}
}
- uint32_t flags;
- return GetSubstitutionInternal(root, result, &flags);
+ return GetSubstitutionInternal(root, result);
}
nsresult SubstitutingProtocolHandler::GetSubstitutionFlags(
@@ -625,7 +624,8 @@ nsresult SubstitutingProtocolHandler::GetSubstitutionFlags(
}
nsCOMPtr<nsIURI> baseURI;
- return GetSubstitutionInternal(root, getter_AddRefs(baseURI), flags);
+ *flags = GetJARFlags(root);
+ return GetSubstitutionInternal(root, getter_AddRefs(baseURI));
}
nsresult SubstitutingProtocolHandler::HasSubstitution(
diff --git a/netwerk/protocol/res/SubstitutingProtocolHandler.h b/netwerk/protocol/res/SubstitutingProtocolHandler.h
index 6bdb27f38a..1d3033a5a0 100644
--- a/netwerk/protocol/res/SubstitutingProtocolHandler.h
+++ b/netwerk/protocol/res/SubstitutingProtocolHandler.h
@@ -58,9 +58,8 @@ class SubstitutingProtocolHandler {
// Override this in the subclass to try additional lookups after checking
// mSubstitutions.
[[nodiscard]] virtual nsresult GetSubstitutionInternal(
- const nsACString& aRoot, nsIURI** aResult, uint32_t* aFlags) {
+ const nsACString& aRoot, nsIURI** aResult) {
*aResult = nullptr;
- *aFlags = 0;
return NS_ERROR_NOT_AVAILABLE;
}
@@ -73,10 +72,11 @@ class SubstitutingProtocolHandler {
return false;
}
- // This method should only return true if GetSubstitutionInternal would
- // return the RESOLVE_JAR_URI flag.
- [[nodiscard]] virtual bool MustResolveJAR(const nsACString& aRoot) {
- return false;
+ // This method should only return RESOLVE_JAR_URI when
+ // GetSubstitutionalInternal will return nsIJARURI instead of a nsIFileURL.
+ // Currently, this only happens on Android.
+ [[nodiscard]] virtual uint32_t GetJARFlags(const nsACString& aRoot) {
+ return 0;
}
// Override this in the subclass to check for special case when opening
diff --git a/netwerk/protocol/res/nsResProtocolHandler.cpp b/netwerk/protocol/res/nsResProtocolHandler.cpp
index 208baedf2b..568f929f35 100644
--- a/netwerk/protocol/res/nsResProtocolHandler.cpp
+++ b/netwerk/protocol/res/nsResProtocolHandler.cpp
@@ -123,20 +123,23 @@ nsResProtocolHandler::AllowContentToAccess(nsIURI* aURI, bool* aResult) {
return NS_OK;
}
+uint32_t nsResProtocolHandler::GetJARFlags(const nsACString& aRoot) {
+ if (aRoot.Equals(kAndroid)) {
+ return nsISubstitutingProtocolHandler::RESOLVE_JAR_URI;
+ }
+
+ // 0 implies no content access.
+ return 0;
+}
+
nsresult nsResProtocolHandler::GetSubstitutionInternal(const nsACString& aRoot,
- nsIURI** aResult,
- uint32_t* aFlags) {
+ nsIURI** aResult) {
nsAutoCString uri;
if (!ResolveSpecialCases(aRoot, "/"_ns, "/"_ns, uri)) {
return NS_ERROR_NOT_AVAILABLE;
}
- if (aRoot.Equals(kAndroid)) {
- *aFlags = nsISubstitutingProtocolHandler::RESOLVE_JAR_URI;
- } else {
- *aFlags = 0; // No content access.
- }
return NS_NewURI(aResult, uri);
}
diff --git a/netwerk/protocol/res/nsResProtocolHandler.h b/netwerk/protocol/res/nsResProtocolHandler.h
index 50e790a53a..3c3781ac67 100644
--- a/netwerk/protocol/res/nsResProtocolHandler.h
+++ b/netwerk/protocol/res/nsResProtocolHandler.h
@@ -48,9 +48,9 @@ class nsResProtocolHandler final
}
protected:
+ [[nodiscard]] uint32_t GetJARFlags(const nsACString& aRoot) override;
[[nodiscard]] nsresult GetSubstitutionInternal(const nsACString& aRoot,
- nsIURI** aResult,
- uint32_t* aFlags) override;
+ nsIURI** aResult) override;
virtual ~nsResProtocolHandler() = default;
[[nodiscard]] bool ResolveSpecialCases(const nsACString& aHost,
@@ -58,10 +58,6 @@ class nsResProtocolHandler final
const nsACString& aPathname,
nsACString& aResult) override;
- [[nodiscard]] virtual bool MustResolveJAR(const nsACString& aRoot) override {
- return aRoot.EqualsLiteral("android");
- }
-
private:
[[nodiscard]] nsresult Init();
static mozilla::StaticRefPtr<nsResProtocolHandler> sSingleton;
diff --git a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
index 3b5f95d5f3..d38cc43586 100644
--- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
+++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
@@ -995,6 +995,18 @@ nsViewSourceChannel::UpgradeToSecure() {
}
NS_IMETHODIMP
+nsViewSourceChannel::GetRequestObserversCalled(bool* aCalled) {
+ return !mHttpChannel ? NS_ERROR_NULL_POINTER
+ : mHttpChannel->GetRequestObserversCalled(aCalled);
+}
+
+NS_IMETHODIMP
+nsViewSourceChannel::SetRequestObserversCalled(bool aCalled) {
+ return !mHttpChannel ? NS_ERROR_NULL_POINTER
+ : mHttpChannel->SetRequestObserversCalled(aCalled);
+}
+
+NS_IMETHODIMP
nsViewSourceChannel::GetRequestContextID(uint64_t* _retval) {
return !mHttpChannel ? NS_ERROR_NULL_POINTER
: mHttpChannel->GetRequestContextID(_retval);
diff --git a/netwerk/protocol/websocket/nsIWebSocketChannel.idl b/netwerk/protocol/websocket/nsIWebSocketChannel.idl
index 7092c3c6b1..555d6d8168 100644
--- a/netwerk/protocol/websocket/nsIWebSocketChannel.idl
+++ b/netwerk/protocol/websocket/nsIWebSocketChannel.idl
@@ -146,7 +146,7 @@ interface nsIWebSocketChannel : nsISupports
in nsIWebSocketListener aListener,
in nsISupports aContext);
- [must_use]
+ [must_use, noscript]
void asyncOpenNative(in nsIURI aURI,
in ACString aOrigin,
in OriginAttributes aOriginAttributes,
diff --git a/netwerk/protocol/webtransport/WebTransportSessionProxy.cpp b/netwerk/protocol/webtransport/WebTransportSessionProxy.cpp
index dd4ba7e7d0..dd01cc6ff8 100644
--- a/netwerk/protocol/webtransport/WebTransportSessionProxy.cpp
+++ b/netwerk/protocol/webtransport/WebTransportSessionProxy.cpp
@@ -27,6 +27,7 @@ namespace mozilla::net {
LazyLogModule webTransportLog("nsWebTransport");
NS_IMPL_ISUPPORTS(WebTransportSessionProxy, WebTransportSessionEventListener,
+ WebTransportSessionEventListenerInternal,
WebTransportConnectionSettings, nsIWebTransport,
nsIRedirectResultListener, nsIStreamListener,
nsIChannelEventSink, nsIInterfaceRequestor);
diff --git a/netwerk/protocol/webtransport/WebTransportSessionProxy.h b/netwerk/protocol/webtransport/WebTransportSessionProxy.h
index 9e6f785d80..23407f3aaa 100644
--- a/netwerk/protocol/webtransport/WebTransportSessionProxy.h
+++ b/netwerk/protocol/webtransport/WebTransportSessionProxy.h
@@ -119,17 +119,20 @@ namespace mozilla::net {
class WebTransportStreamCallbackWrapper;
-class WebTransportSessionProxy final : public nsIWebTransport,
- public WebTransportSessionEventListener,
- public WebTransportConnectionSettings,
- public nsIStreamListener,
- public nsIChannelEventSink,
- public nsIRedirectResultListener,
- public nsIInterfaceRequestor {
+class WebTransportSessionProxy final
+ : public nsIWebTransport,
+ public WebTransportSessionEventListener,
+ public WebTransportSessionEventListenerInternal,
+ public WebTransportConnectionSettings,
+ public nsIStreamListener,
+ public nsIChannelEventSink,
+ public nsIRedirectResultListener,
+ public nsIInterfaceRequestor {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIWEBTRANSPORT
NS_DECL_WEBTRANSPORTSESSIONEVENTLISTENER
+ NS_DECL_WEBTRANSPORTSESSIONEVENTLISTENERINTERNAL
NS_DECL_WEBTRANSPORTCONNECTIONSETTINGS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
diff --git a/netwerk/protocol/webtransport/nsIWebTransport.idl b/netwerk/protocol/webtransport/nsIWebTransport.idl
index 5ed4e96517..3afe9979ba 100644
--- a/netwerk/protocol/webtransport/nsIWebTransport.idl
+++ b/netwerk/protocol/webtransport/nsIWebTransport.idl
@@ -44,6 +44,7 @@ interface nsIWebTransport : nsISupports {
in unsigned long aSecurityFlags,
in WebTransportSessionEventListener aListener);
+ [noscript]
void asyncConnectWithClient(in nsIURI aURI,
in boolean aDedicated,
in Array<nsIWebTransportHash> aServerCertHashes,
@@ -79,9 +80,6 @@ interface WebTransportSessionEventListener : nsISupports {
// This is used to let the consumer of nsIWebTransport know that the
// underlying WebTransportSession object is ready to use.
void onSessionReady(in uint64_t aSessionId);
- // This is used internally to pass the reference of WebTransportSession
- // object to WebTransportSessionProxy.
- void onSessionReadyInternal(in Http3WebTransportSessionPtr aSession);
void onSessionClosed(in boolean aCleanly,
in uint32_t aErrorCode,
in ACString aReason);
@@ -90,19 +88,12 @@ interface WebTransportSessionEventListener : nsISupports {
void onIncomingBidirectionalStreamAvailable(in nsIWebTransportBidirectionalStream aStream);
void onIncomingUnidirectionalStreamAvailable(in nsIWebTransportReceiveStream aStream);
- // This is used internally to pass the reference of Http3WebTransportStream
- // object to WebTransportSessionProxy.
- void onIncomingStreamAvailableInternal(in Http3WebTransportStreamPtr aStream);
-
void onStopSending(in uint64_t aStreamId, in nsresult aError);
void onResetReceived(in uint64_t aStreamId, in nsresult aError);
// When a new datagram has been received.
void onDatagramReceived(in Array<uint8_t> aData);
- // This is used internally to pass the datagram to WebTransportSessionProxy.
- void onDatagramReceivedInternal(in Datagram aData);
-
void onMaxDatagramSize(in uint64_t aSize);
cenum DatagramOutcome: 32 {
@@ -118,6 +109,20 @@ interface WebTransportSessionEventListener : nsISupports {
// void onStatsAvailable(in WebTransportStats aStats);
};
+[uuid(8fb30aa9-5163-4eb3-81f3-371e1ccb5b0e)]
+interface WebTransportSessionEventListenerInternal : nsISupports {
+ // This is used internally to pass the reference of WebTransportSession
+ // object to WebTransportSessionProxy.
+ void onSessionReadyInternal(in Http3WebTransportSessionPtr aSession);
+
+ // This is used internally to pass the reference of Http3WebTransportStream
+ // object to WebTransportSessionProxy.
+ void onIncomingStreamAvailableInternal(in Http3WebTransportStreamPtr aStream);
+
+ // This is used internally to pass the datagram to WebTransportSessionProxy.
+ void onDatagramReceivedInternal(in Datagram aData);
+};
+
[uuid(faad75bd-83c6-420b-9fdb-a70bd70be449)]
interface WebTransportConnectionSettings : nsISupports {
// WebTransport specific connection information
diff --git a/netwerk/socket/neqo_glue/Cargo.toml b/netwerk/socket/neqo_glue/Cargo.toml
index 8355c54c19..dfcd0d8244 100644
--- a/netwerk/socket/neqo_glue/Cargo.toml
+++ b/netwerk/socket/neqo_glue/Cargo.toml
@@ -9,16 +9,16 @@ license = "MPL-2.0"
name = "neqo_glue"
[dependencies]
-neqo-http3 = { tag = "v0.7.5", git = "https://github.com/mozilla/neqo" }
-neqo-transport = { tag = "v0.7.5", git = "https://github.com/mozilla/neqo" }
-neqo-common = { tag = "v0.7.5", git = "https://github.com/mozilla/neqo" }
-neqo-qpack = { tag = "v0.7.5", git = "https://github.com/mozilla/neqo" }
+neqo-http3 = { tag = "v0.7.7", git = "https://github.com/mozilla/neqo" }
+neqo-transport = { tag = "v0.7.7", git = "https://github.com/mozilla/neqo" }
+neqo-common = { tag = "v0.7.7", git = "https://github.com/mozilla/neqo" }
+neqo-qpack = { tag = "v0.7.7", git = "https://github.com/mozilla/neqo" }
nserror = { path = "../../../xpcom/rust/nserror" }
nsstring = { path = "../../../xpcom/rust/nsstring" }
xpcom = { path = "../../../xpcom/rust/xpcom" }
thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
log = "0.4.0"
-qlog = "0.12"
+qlog = "0.13"
libc = "0.2.0"
static_prefs = { path = "../../../modules/libpref/init/static_prefs"}
uuid = { version = "1.0", features = ["v4"] }
@@ -27,7 +27,7 @@ uuid = { version = "1.0", features = ["v4"] }
winapi = {version = "0.3", features = ["ws2def"] }
[dependencies.neqo-crypto]
-tag = "v0.7.5"
+tag = "v0.7.7"
git = "https://github.com/mozilla/neqo"
default-features = false
features = ["gecko"]
diff --git a/netwerk/socket/neqo_glue/src/lib.rs b/netwerk/socket/neqo_glue/src/lib.rs
index fd527a7fb9..9f11a783be 100644
--- a/netwerk/socket/neqo_glue/src/lib.rs
+++ b/netwerk/socket/neqo_glue/src/lib.rs
@@ -671,11 +671,11 @@ impl From<TransportError> for CloseError {
}
}
-impl From<neqo_transport::ConnectionError> for CloseError {
- fn from(error: neqo_transport::ConnectionError) -> CloseError {
+impl From<neqo_transport::CloseReason> for CloseError {
+ fn from(error: neqo_transport::CloseReason) -> CloseError {
match error {
- neqo_transport::ConnectionError::Transport(c) => c.into(),
- neqo_transport::ConnectionError::Application(c) => CloseError::AppError(c),
+ neqo_transport::CloseReason::Transport(c) => c.into(),
+ neqo_transport::CloseReason::Application(c) => CloseError::AppError(c),
}
}
}
@@ -1056,12 +1056,11 @@ pub extern "C" fn neqo_http3conn_event(
Http3State::Connected => Http3Event::ConnectionConnected,
Http3State::Closing(error_code) => {
match error_code {
- neqo_transport::ConnectionError::Transport(
- TransportError::CryptoError(neqo_crypto::Error::EchRetry(ref c)),
- )
- | neqo_transport::ConnectionError::Transport(TransportError::EchRetry(
- ref c,
- )) => {
+ neqo_transport::CloseReason::Transport(TransportError::CryptoError(
+ neqo_crypto::Error::EchRetry(ref c),
+ ))
+ | neqo_transport::CloseReason::Transport(TransportError::EchRetry(ref c)) =>
+ {
data.extend_from_slice(c.as_ref());
}
_ => {}
@@ -1072,12 +1071,11 @@ pub extern "C" fn neqo_http3conn_event(
}
Http3State::Closed(error_code) => {
match error_code {
- neqo_transport::ConnectionError::Transport(
- TransportError::CryptoError(neqo_crypto::Error::EchRetry(ref c)),
- )
- | neqo_transport::ConnectionError::Transport(TransportError::EchRetry(
- ref c,
- )) => {
+ neqo_transport::CloseReason::Transport(TransportError::CryptoError(
+ neqo_crypto::Error::EchRetry(ref c),
+ ))
+ | neqo_transport::CloseReason::Transport(TransportError::EchRetry(ref c)) =>
+ {
data.extend_from_slice(c.as_ref());
}
_ => {}
diff --git a/netwerk/socket/nsINamedPipeService.idl b/netwerk/socket/nsINamedPipeService.idl
index 9db557577d..ce189ae9d3 100644
--- a/netwerk/socket/nsINamedPipeService.idl
+++ b/netwerk/socket/nsINamedPipeService.idl
@@ -12,7 +12,7 @@
* This is the callback interface for nsINamedPipeService.
* The functions are called by the internal thread in the nsINamedPipeService.
*/
-[scriptable, uuid(de4f460b-94fd-442c-9002-1637beb2185a)]
+[uuid(de4f460b-94fd-442c-9002-1637beb2185a)]
interface nsINamedPipeDataObserver : nsISupports
{
/**
@@ -41,7 +41,7 @@ interface nsINamedPipeDataObserver : nsISupports
/**
* nsINamedPipeService
*/
-[scriptable, uuid(1bf19133-5625-4ac8-836a-80b1c215f72b)]
+[uuid(1bf19133-5625-4ac8-836a-80b1c215f72b)]
interface nsINamedPipeService : nsISupports
{
/**
diff --git a/netwerk/system/android/nsAndroidNetworkLinkService.cpp b/netwerk/system/android/nsAndroidNetworkLinkService.cpp
index 850ac5b565..a3d0328d8b 100644
--- a/netwerk/system/android/nsAndroidNetworkLinkService.cpp
+++ b/netwerk/system/android/nsAndroidNetworkLinkService.cpp
@@ -9,6 +9,7 @@
#include "nsIObserverService.h"
#include "mozilla/StaticPrefs_network.h"
+#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Services.h"
#include "mozilla/Logging.h"
diff --git a/netwerk/system/linux/nsNetworkLinkService.cpp b/netwerk/system/linux/nsNetworkLinkService.cpp
index 363b058eed..59894ba1fa 100644
--- a/netwerk/system/linux/nsNetworkLinkService.cpp
+++ b/netwerk/system/linux/nsNetworkLinkService.cpp
@@ -8,6 +8,7 @@
#include "nsNetworkLinkService.h"
#include "nsString.h"
#include "mozilla/Logging.h"
+#include "mozilla/IntegerPrintfMacros.h"
#include "nsNetAddr.h"
#include "mozilla/StaticPrefs_network.h"
diff --git a/netwerk/system/win32/nsNotifyAddrListener.cpp b/netwerk/system/win32/nsNotifyAddrListener.cpp
index a64206fbc6..6174754c8c 100644
--- a/netwerk/system/win32/nsNotifyAddrListener.cpp
+++ b/netwerk/system/win32/nsNotifyAddrListener.cpp
@@ -600,7 +600,7 @@ nsNotifyAddrListener::CheckAdaptersAddresses(void) {
list.StripWhitespace();
for (const nsACString& suffix : list.Split(',')) {
LOG((" appending DNS suffix from registry: %s\n",
- suffix.BeginReading()));
+ PromiseFlatCString(suffix).get()));
if (!suffix.IsEmpty()) {
dnsSuffixList.AppendElement(suffix);
}
diff --git a/netwerk/test/browser/browser.toml b/netwerk/test/browser/browser.toml
index 002bd2769d..a12ffed212 100644
--- a/netwerk/test/browser/browser.toml
+++ b/netwerk/test/browser/browser.toml
@@ -72,6 +72,7 @@ support-files = [
"x_frame_options.html^headers^",
"test_1629307.html",
"file_link_header.sjs",
+ "file_link_dns_prefetch.sjs",
]
prefs = [
@@ -156,6 +157,8 @@ skip-if = ["os == 'win'"] # Bug 1775761
["browser_cookie_sync_across_tabs.js"]
+["browser_dns_prefetch_link_header.js"]
+
["browser_fetch_lnk.js"]
run-if = ["os == 'win'"]
support-files = ["file_lnk.lnk",]
diff --git a/netwerk/test/browser/browser_dns_prefetch_link_header.js b/netwerk/test/browser/browser_dns_prefetch_link_header.js
new file mode 100644
index 0000000000..a7954cadb5
--- /dev/null
+++ b/netwerk/test/browser/browser_dns_prefetch_link_header.js
@@ -0,0 +1,282 @@
+/* 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/. */
+
+// Test steps:
+// 1. Load file_link_dns_prefetch.sjs
+// 2.`<link rel="dns-prefetch" href="https://example.org">` is in
+// the server-side sjs, so we will make the dns-request.
+// 3. We verify that the dns request was made
+
+const gDashboard = Cc["@mozilla.org/network/dashboard;1"].getService(
+ Ci.nsIDashboard
+);
+
+/////////////////////////////////////////////////////////////////////////////
+// To observe DNS requests when running via the mochitest proxy we must first take a few steps:
+//
+// 1. Update the mochitest proxy pac file to include dns resolution.
+// We do this by injecting "dnsResolve(host);" into the `FindProxyForURL()` pac function.
+let existingPACScript = Services.prefs.getCharPref(
+ "network.proxy.autoconfig_url"
+);
+
+let findProxyForURLFunction = "function FindProxyForURL(url, host){";
+let directDnsPacScript = existingPACScript.replace(
+ findProxyForURLFunction,
+ `${findProxyForURLFunction}
+ dnsResolve(host);
+ `
+);
+Services.prefs.setStringPref(
+ "network.proxy.autoconfig_url",
+ directDnsPacScript
+);
+
+// 2. Ensure we don't disable dns prefetch despite using a proxy (this would otherwise happen after every request that the proxy completed)
+Services.prefs.setBoolPref("network.dns.prefetch_via_proxy", true);
+
+// 3. And finally enable dns prefetching via the private dns service api (generally disabled in mochitest proxy)
+Services.dns.QueryInterface(Ci.nsPIDNSService).prefetchEnabled = true;
+/////////////////////////////////////////////////////////////////////////////
+
+registerCleanupFunction(function () {
+ // Restore proxy pac and dns prefetch behaviour via proxy
+ Services.prefs.setCharPref("network.proxy.autoconfig_url", existingPACScript);
+ Services.prefs.clearUserPref("network.dns.prefetch_via_proxy");
+ Services.dns.QueryInterface(Ci.nsPIDNSService).prefetchEnabled = false;
+});
+
+async function isRecordFound(hostname) {
+ return new Promise(resolve => {
+ gDashboard.requestDNSInfo(function (data) {
+ let found = false;
+ for (let i = 0; i < data.entries.length; i++) {
+ if (data.entries[i].hostname == hostname) {
+ found = true;
+ break;
+ }
+ }
+ resolve(found);
+ });
+ });
+}
+
+let https_requestUrl = `https://example.com/browser/netwerk/test/browser/file_link_dns_prefetch.sjs`;
+let http_requestUrl = `http://example.com/browser/netwerk/test/browser/file_link_dns_prefetch.sjs`; // eslint-disable-line @microsoft/sdl/no-insecure-url
+
+// Test dns-prefetch on https
+add_task(async function test_https_dns_prefetch() {
+ Services.dns.clearCache(true);
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: https_requestUrl,
+ waitForLoad: true,
+ },
+ async function () {}
+ );
+
+ Assert.ok(
+ await TestUtils.waitForCondition(() => {
+ return isRecordFound("example.org");
+ }),
+ "Record from link rel=dns-prefetch element should be found"
+ );
+ Assert.ok(await isRecordFound("example.com"), "Host record should be found");
+});
+
+// Test dns-prefetch on http
+add_task(async function test_http_dns_prefetch() {
+ Services.dns.clearCache(true);
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: http_requestUrl,
+ waitForLoad: true,
+ },
+ async function () {}
+ );
+
+ Assert.ok(
+ await TestUtils.waitForCondition(() => {
+ return isRecordFound("example.org");
+ }),
+ "Record from link rel=dns-prefetch element should be found"
+ );
+ Assert.ok(await isRecordFound("example.com"), "Host record should be found");
+});
+
+// Test dns-prefetch on https with the feature disabled
+add_task(async function test_https_dns_prefetch_disabled() {
+ Services.dns.clearCache(true);
+
+ // Disable the feature to verify that it will not prefetch
+ Services.prefs.setBoolPref("network.dns.disablePrefetchFromHTTPS", true);
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: https_requestUrl,
+ waitForLoad: true,
+ },
+ async function () {}
+ );
+
+ Assert.ok(await isRecordFound("example.com"), "Host record should be found");
+ Assert.ok(
+ !(await isRecordFound("example.org")),
+ "Record from link rel=dns-prefetch element should not be found with disablePrefetchFromHTTPS set"
+ );
+
+ Services.prefs.clearUserPref("network.dns.disablePrefetchFromHTTPS");
+});
+
+// Test dns-prefetch on http with the feature disabled
+add_task(async function test_http_dns_prefetch_disabled() {
+ Services.dns.clearCache(true);
+
+ // Disable the feature to verify, but this test is http, and so prefetch will execute
+ Services.prefs.setBoolPref("network.dns.disablePrefetchFromHTTPS", true);
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: http_requestUrl,
+ waitForLoad: true,
+ },
+ async function () {}
+ );
+
+ Assert.ok(
+ await TestUtils.waitForCondition(() => {
+ return isRecordFound("example.org");
+ }),
+ "Record from link rel=dns-prefetch element should be found on http page with disablePrefetchFromHTTPS set"
+ );
+ Assert.ok(await isRecordFound("example.com"), "Host record should be found");
+
+ Services.prefs.clearUserPref("network.dns.disablePrefetchFromHTTPS");
+});
+
+// Test if we speculatively prefetch dns for anchor elements on https documents
+add_task(async function test_https_anchor_speculative_dns_prefetch() {
+ Services.dns.clearCache(true);
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: https_requestUrl,
+ waitForLoad: true,
+ },
+ async function () {
+ Assert.ok(
+ await isRecordFound("example.com"),
+ "Host record should be found"
+ );
+ Assert.ok(
+ !(await isRecordFound("www.mozilla.org")),
+ "By default we do not speculatively prefetch dns for anchor elements on https documents"
+ );
+ }
+ );
+
+ // And enable the pref to verify that it works
+ Services.prefs.setBoolPref(
+ "dom.prefetch_dns_for_anchor_https_document",
+ true
+ );
+ Services.dns.clearCache(true);
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: https_requestUrl,
+ waitForLoad: true,
+ },
+ async function () {
+ // The anchor element prefetchs are sent after pageload event; wait for them
+ Assert.ok(
+ await TestUtils.waitForCondition(() => {
+ return isRecordFound("www.mozilla.org");
+ }),
+ "Speculatively prefetch dns for anchor elements on https documents"
+ );
+ Assert.ok(
+ await isRecordFound("example.com"),
+ "Host record should be found"
+ );
+ }
+ );
+
+ Services.prefs.clearUserPref("dom.prefetch_dns_for_anchor_https_document");
+});
+
+// Test that we speculatively prefetch dns for anchor elements on http documents
+add_task(async function test_http_anchor_speculative_dns_prefetch() {
+ Services.dns.clearCache(true);
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: http_requestUrl,
+ waitForLoad: true,
+ },
+ async function () {
+ Assert.ok(
+ await TestUtils.waitForCondition(() => {
+ return isRecordFound("example.org");
+ }),
+ "Record from link rel=dns-prefetch element should be found"
+ );
+
+ // The anchor element prefetchs are sent after pageload event; wait for them
+ Assert.ok(
+ await TestUtils.waitForCondition(() => {
+ return isRecordFound("www.mozilla.org");
+ }),
+ "By default we speculatively prefetch dns for anchor elements on http documents"
+ );
+
+ Assert.ok(
+ await isRecordFound("example.com"),
+ "Host record should be found"
+ );
+ }
+ );
+
+ // And disable the pref to verify that we no longer make the requests
+ Services.prefs.setBoolPref(
+ "dom.prefetch_dns_for_anchor_http_document",
+ false
+ );
+ Services.dns.clearCache(true);
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: http_requestUrl,
+ waitForLoad: true,
+ },
+ async function () {
+ Assert.ok(
+ await TestUtils.waitForCondition(() => {
+ return isRecordFound("example.org");
+ }),
+ "Record from link rel=dns-prefetch element should be found"
+ );
+ Assert.ok(
+ !(await isRecordFound("www.mozilla.org")),
+ "We disabled speculative prefetch dns for anchor elements on http documents"
+ );
+ Assert.ok(
+ await isRecordFound("example.com"),
+ "Host record should be found"
+ );
+ }
+ );
+
+ Services.prefs.clearUserPref("dom.prefetch_dns_for_anchor_http_document");
+});
diff --git a/netwerk/test/browser/file_link_dns_prefetch.sjs b/netwerk/test/browser/file_link_dns_prefetch.sjs
new file mode 100644
index 0000000000..6ca959bda1
--- /dev/null
+++ b/netwerk/test/browser/file_link_dns_prefetch.sjs
@@ -0,0 +1,25 @@
+"use strict";
+
+function handleRequest(request, response) {
+ // write to raw socket
+ response.seizePower();
+ let body = `<!DOCTYPE html>
+ <html>
+ <head>
+ <link rel="dns-prefetch" href="https://example.org">
+ </head>
+ <body>
+ <h1>Test rel=dns-prefetch<h1>
+ <a href="https://www.mozilla.org"> Test link </a>
+ </body>
+ </html>`;
+
+ response.write("HTTP/1.1 200 OK\r\n");
+ response.write("Content-Type: text/html;charset=utf-8\r\n");
+ response.write("Cache-Control: no-cache\r\n");
+ response.write(`Content-Length: ${body.length}\r\n`);
+ response.write("\r\n");
+ response.write(body);
+
+ response.finish();
+}
diff --git a/netwerk/test/gtest/TestCommon.h b/netwerk/test/gtest/TestCommon.h
index 0d2fd74e5b..76620fbb44 100644
--- a/netwerk/test/gtest/TestCommon.h
+++ b/netwerk/test/gtest/TestCommon.h
@@ -17,8 +17,8 @@ class WaitForCondition final : public nsIRunnable {
NS_DECL_THREADSAFE_ISUPPORTS
void Wait(int pending) {
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(mPending == 0);
+ MOZ_RELEASE_ASSERT(NS_IsMainThread());
+ MOZ_RELEASE_ASSERT(mPending == 0);
mPending = pending;
mozilla::SpinEventLoopUntil("TestCommon.h:WaitForCondition::Wait"_ns,
@@ -32,8 +32,8 @@ class WaitForCondition final : public nsIRunnable {
virtual ~WaitForCondition() = default;
NS_IMETHOD Run() override {
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(mPending);
+ MOZ_RELEASE_ASSERT(NS_IsMainThread());
+ MOZ_RELEASE_ASSERT(mPending);
--mPending;
return NS_OK;
diff --git a/netwerk/test/gtest/TestCookie.cpp b/netwerk/test/gtest/TestCookie.cpp
index 4812ee47f1..e99e9f6332 100644
--- a/netwerk/test/gtest/TestCookie.cpp
+++ b/netwerk/test/gtest/TestCookie.cpp
@@ -95,7 +95,7 @@ void SetACookieInternal(nsICookieService* aCookieService, const char* aSpec,
/* shouldResistFingerprinting */ false)
: CookieJarSettings::GetBlockingAll(
/* shouldResistFingerprinting */ false);
- MOZ_ASSERT(cookieJarSettings);
+ MOZ_RELEASE_ASSERT(cookieJarSettings);
nsCOMPtr<nsILoadInfo> loadInfo = dummyChannel->LoadInfo();
loadInfo->SetCookieJarSettings(cookieJarSettings);
@@ -140,7 +140,7 @@ void GetACookieNoHttp(nsICookieService* aCookieService, const char* aSpec,
RefPtr<BasePrincipal> principal =
BasePrincipal::CreateContentPrincipal(uri, OriginAttributes());
- MOZ_ASSERT(principal);
+ MOZ_RELEASE_ASSERT(principal);
nsCOMPtr<mozilla::dom::Document> document;
nsresult rv = NS_NewDOMDocument(getter_AddRefs(document),
diff --git a/netwerk/test/gtest/TestIDNA.cpp b/netwerk/test/gtest/TestIDNA.cpp
index 544debbd43..56b05025d7 100644
--- a/netwerk/test/gtest/TestIDNA.cpp
+++ b/netwerk/test/gtest/TestIDNA.cpp
@@ -3,6 +3,9 @@
#include "gtest/BlackBox.h"
#include "nsNetUtil.h"
+#include "nsIURI.h"
+#include "nsCOMPtr.h"
+#include "mozilla/Encoding.h"
#define TEST_COUNT 10000
@@ -10,7 +13,7 @@ class TestIDNA : public ::testing::Test {
protected:
void SetUp() override {
// Intentionally Assign and not AssignLiteral
- // to simulate the usual heap case.
+ // to simulate the heap case.
mPlainASCII.Assign("example.com");
mLeadingDigitASCII.Assign("1test.example");
mUnicodeMixed.Assign("مثال.example");
@@ -20,6 +23,16 @@ class TestIDNA : public ::testing::Test {
mUnicodeRTL.Assign("الاسم.مثال");
mPunycodeRTL.Assign("xn--mgba0b1dh.xn--mgbh0fb");
// Intentionally not assigning to mEmpty
+
+ // For measuring the case inside nsStandardURL
+ mUrlPlainASCII.Assign("https://example.com/");
+ mUrlLeadingDigitASCII.Assign("https://1test.example/");
+ mUrlUnicodeMixed.Assign("https://مثال.example/");
+ mUrlPunycodeMixed.Assign("https://xn--mgbh0fb.example/");
+ mUrlUnicodeLTR.Assign("https://නම.උදාහරණ/");
+ mUrlPunycodeLTR.Assign("https://xn--r0co.xn--ozc8dl2c3bxd/");
+ mUrlUnicodeRTL.Assign("https://الاسم.مثال/");
+ mUrlPunycodeRTL.Assign("https://xn--mgba0b1dh.xn--mgbh0fb/");
}
public:
@@ -32,6 +45,14 @@ class TestIDNA : public ::testing::Test {
nsCString mUnicodeRTL;
nsCString mPunycodeRTL;
nsCString mEmpty; // Extremely suspicious measurement!
+ nsCString mUrlPlainASCII;
+ nsCString mUrlLeadingDigitASCII;
+ nsCString mUrlUnicodeMixed;
+ nsCString mUrlPunycodeMixed;
+ nsCString mUrlUnicodeLTR;
+ nsCString mUrlPunycodeLTR;
+ nsCString mUrlUnicodeRTL;
+ nsCString mUrlPunycodeRTL;
};
#define IDNA_ITERATIONS 50000
@@ -44,6 +65,17 @@ class TestIDNA : public ::testing::Test {
} \
});
+#define IDNA_URL_BENCH(name, src) \
+ MOZ_GTEST_BENCH_F(TestIDNA, name, [this] { \
+ for (int i = 0; i < IDNA_ITERATIONS; i++) { \
+ nsCOMPtr<nsIURI> dst; \
+ nsresult rv = NS_NewURI(getter_AddRefs(dst), *mozilla::BlackBox(&src), \
+ UTF_8_ENCODING); \
+ ASSERT_EQ(NS_OK, rv); \
+ mozilla::BlackBox(&dst); \
+ } \
+ });
+
IDNA_BENCH(BenchToASCIIPlainASCII, NS_DomainToASCII, mPlainASCII);
IDNA_BENCH(BenchToASCIILeadingDigitASCII, NS_DomainToASCII, mLeadingDigitASCII);
IDNA_BENCH(BenchToASCIIUnicodeMixed, NS_DomainToASCII, mUnicodeMixed);
@@ -75,3 +107,12 @@ IDNA_BENCH(BenchToUnicodePunycodeLTR, NS_DomainToUnicode, mPunycodeLTR);
IDNA_BENCH(BenchToUnicodeUnicodeRTL, NS_DomainToUnicode, mUnicodeRTL);
IDNA_BENCH(BenchToUnicodePunycodeRTL, NS_DomainToUnicode, mPunycodeRTL);
IDNA_BENCH(BenchToUnicodeEmpty, NS_DomainToUnicode, mEmpty);
+
+IDNA_URL_BENCH(BenchUrlPlainASCII, mUrlPlainASCII);
+IDNA_URL_BENCH(BenchUrlLeadingDigitASCII, mUrlLeadingDigitASCII);
+IDNA_URL_BENCH(BenchUrlUnicodeMixed, mUrlUnicodeMixed);
+IDNA_URL_BENCH(BenchUrlPunycodeMixed, mUrlPunycodeMixed);
+IDNA_URL_BENCH(BenchUrlUnicodeLTR, mUrlUnicodeLTR);
+IDNA_URL_BENCH(BenchUrlPunycodeLTR, mUrlPunycodeLTR);
+IDNA_URL_BENCH(BenchUrlUnicodeRTL, mUrlUnicodeRTL);
+IDNA_URL_BENCH(BenchUrlPunycodeRTL, mUrlPunycodeRTL);
diff --git a/netwerk/test/gtest/TestInputStreamTransport.cpp b/netwerk/test/gtest/TestInputStreamTransport.cpp
index 43df0e193a..de19f48147 100644
--- a/netwerk/test/gtest/TestInputStreamTransport.cpp
+++ b/netwerk/test/gtest/TestInputStreamTransport.cpp
@@ -29,7 +29,7 @@ void CreateStream(already_AddRefed<nsIInputStream> aSource,
ASSERT_EQ(NS_OK, rv);
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(wrapper);
- MOZ_ASSERT(asyncStream);
+ MOZ_RELEASE_ASSERT(asyncStream);
asyncStream.forget(aStream);
}
diff --git a/netwerk/test/gtest/TestNamedPipeService.cpp b/netwerk/test/gtest/TestNamedPipeService.cpp
index b91a17a93e..ef764dde13 100644
--- a/netwerk/test/gtest/TestNamedPipeService.cpp
+++ b/netwerk/test/gtest/TestNamedPipeService.cpp
@@ -31,7 +31,7 @@ class Event {
void Set() {
MonitorAutoLock lock(mMonitor);
- MOZ_ASSERT(!mSignaled);
+ MOZ_RELEASE_ASSERT(!mSignaled);
mSignaled = true;
mMonitor.Notify();
}
diff --git a/netwerk/test/gtest/moz.build b/netwerk/test/gtest/moz.build
index 8e0d66f4e2..a0333ecde7 100644
--- a/netwerk/test/gtest/moz.build
+++ b/netwerk/test/gtest/moz.build
@@ -23,6 +23,7 @@ UNIFIED_SOURCES += [
"TestLinkHeader.cpp",
"TestMIMEInputStream.cpp",
"TestMozURL.cpp",
+ "TestPACMan.cpp",
"TestProtocolProxyService.cpp",
"TestReadStreamToString.cpp",
"TestServerTimingHeader.cpp",
@@ -30,24 +31,15 @@ UNIFIED_SOURCES += [
"TestSSLTokensCache.cpp",
"TestStandardURL.cpp",
"TestUDPSocket.cpp",
+ "TestURIMutator.cpp",
]
if CONFIG["OS_TARGET"] == "WINNT":
UNIFIED_SOURCES += [
"TestNamedPipeService.cpp",
+ "TestNetworkLinkIdHashingWindows.cpp",
]
-# skip the test on windows10-aarch64
-if not (CONFIG["OS_TARGET"] == "WINNT" and CONFIG["TARGET_CPU"] == "aarch64"):
- UNIFIED_SOURCES += [
- "TestPACMan.cpp",
- "TestURIMutator.cpp",
- ]
-
-# run the test on windows only
-if CONFIG["OS_TARGET"] == "WINNT":
- UNIFIED_SOURCES += ["TestNetworkLinkIdHashingWindows.cpp"]
-
# run the test on mac only
if CONFIG["TARGET_OS"] == "OSX":
UNIFIED_SOURCES += ["TestNetworkLinkIdHashingDarwin.cpp"]
diff --git a/netwerk/test/http3server/Cargo.toml b/netwerk/test/http3server/Cargo.toml
index 4905760d3d..d2413636f7 100644
--- a/netwerk/test/http3server/Cargo.toml
+++ b/netwerk/test/http3server/Cargo.toml
@@ -6,10 +6,10 @@ edition = "2018"
license = "MPL-2.0"
[dependencies]
-neqo-transport = { tag = "v0.7.5", git = "https://github.com/mozilla/neqo" }
-neqo-common = { tag = "v0.7.5", git = "https://github.com/mozilla/neqo" }
-neqo-http3 = { tag = "v0.7.5", git = "https://github.com/mozilla/neqo" }
-neqo-qpack = { tag = "v0.7.5", git = "https://github.com/mozilla/neqo" }
+neqo-transport = { tag = "v0.7.7", git = "https://github.com/mozilla/neqo" }
+neqo-common = { tag = "v0.7.7", git = "https://github.com/mozilla/neqo" }
+neqo-http3 = { tag = "v0.7.7", git = "https://github.com/mozilla/neqo" }
+neqo-qpack = { tag = "v0.7.7", git = "https://github.com/mozilla/neqo" }
mio = "0.6.17"
mio-extras = "2.0.5"
log = "0.4.0"
@@ -21,7 +21,7 @@ tokio = { version = "1", features = ["rt-multi-thread"] }
mozilla-central-workspace-hack = { version = "0.1", features = ["http3server"], optional = true }
[dependencies.neqo-crypto]
-tag = "v0.7.5"
+tag = "v0.7.7"
git = "https://github.com/mozilla/neqo"
default-features = false
features = ["gecko"]
diff --git a/netwerk/test/unit/head_channels.js b/netwerk/test/unit/head_channels.js
index ca16bd2835..94a20b0a3d 100644
--- a/netwerk/test/unit/head_channels.js
+++ b/netwerk/test/unit/head_channels.js
@@ -480,7 +480,7 @@ function bytesToString(bytes) {
function check_http_info(request, expected_httpVersion, expected_proxy) {
let httpVersion = "";
try {
- httpVersion = request.protocolVersion;
+ httpVersion = request.QueryInterface(Ci.nsIHttpChannel).protocolVersion;
} catch (e) {}
request.QueryInterface(Ci.nsIProxiedChannel);
diff --git a/netwerk/test/unit/test_cookies_privatebrowsing.js b/netwerk/test/unit/test_cookies_privatebrowsing.js
index 9d3528440a..dab719954e 100644
--- a/netwerk/test/unit/test_cookies_privatebrowsing.js
+++ b/netwerk/test/unit/test_cookies_privatebrowsing.js
@@ -96,10 +96,21 @@ add_task(async () => {
Services.cookies.setCookieStringFromHttp(uri2, "oh=hai; max-age=1000", chan2);
Assert.equal(await getCookieStringFromPrivateDocument(uri2.spec), "oh=hai");
+ // on android fission the privateBrowsingHolder prevents
+ // the cookies on the content process from being updated
+ // Let's release the last PB window.
+ await privateBrowsingHolder.close();
+
// Fake a profile change.
await promise_close_profile();
do_load_profile();
+ // keep the private browsing window open again
+ const privateBrowsingHolder2 = await CookieXPCShellUtils.loadContentPage(
+ "http://bar.com/",
+ { privateBrowsing: true }
+ );
+
// We're still in private browsing mode, but should have a new session.
// Check counts.
Assert.equal(await getCookieStringFromPrivateDocument(uri1.spec), "");
@@ -127,6 +138,6 @@ add_task(async () => {
Assert.equal(Services.cookies.countCookiesFromHost(uri2.host), 0);
// Let's release the last PB window.
- privateBrowsingHolder.close();
+ await privateBrowsingHolder2.close();
Services.prefs.clearUserPref("dom.security.https_first");
});
diff --git a/netwerk/test/unit/test_dns_override.js b/netwerk/test/unit/test_dns_override.js
index f092dd531c..75fc69c289 100644
--- a/netwerk/test/unit/test_dns_override.js
+++ b/netwerk/test/unit/test_dns_override.js
@@ -353,7 +353,10 @@ function hexToUint8Array(hex) {
add_task(
{
- skip_if: () => mozinfo.os == "win" || mozinfo.os == "android",
+ skip_if: () =>
+ mozinfo.os == "win" ||
+ mozinfo.os == "android" ||
+ mozinfo.socketprocess_networking,
},
async function test_https_record_override() {
let trrServer = new TRRServer();
@@ -414,6 +417,7 @@ add_task(
Services.prefs.setBoolPref("network.dns.native_https_query", true);
registerCleanupFunction(async () => {
Services.prefs.clearUserPref("network.dns.native_https_query");
+ Services.prefs.clearUserPref("network.trr.excluded-domains");
});
let listener = new Listener();
@@ -511,5 +515,24 @@ add_task(
"def...",
"got correct answer"
);
+
+ // Adding "service.com" into excluded-domains should fail
+ // native HTTPS query.
+ Services.prefs.setCharPref("network.trr.excluded-domains", "service.com");
+ listener = new Listener();
+ try {
+ Services.dns.asyncResolve(
+ "service.com",
+ Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
+ 0,
+ null,
+ listener,
+ mainThread,
+ defaultOriginAttributes
+ );
+ Assert.ok(false, "asyncResolve should fail");
+ } catch (e) {
+ Assert.equal(e.result, Cr.NS_ERROR_UNKNOWN_HOST);
+ }
}
);
diff --git a/netwerk/test/unit/test_httpssvc_iphint.js b/netwerk/test/unit/test_httpssvc_iphint.js
index 13d9a7e648..40f6727e08 100644
--- a/netwerk/test/unit/test_httpssvc_iphint.js
+++ b/netwerk/test/unit/test_httpssvc_iphint.js
@@ -316,7 +316,7 @@ add_task(async function testIPHintWithFreshDNS() {
);
let chan = makeChan(`https://test.iphint.org/server-timing`);
- chan.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
+ chan.loadFlags |= Ci.nsIRequest.LOAD_FRESH_CONNECTION;
let [req] = await channelOpenPromise(
chan,
CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL
@@ -337,7 +337,7 @@ add_task(async function testIPHintWithFreshDNS() {
});
chan = makeChan(`https://test.iphint.org/server-timing`);
- chan.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
+ chan.loadFlags |= Ci.nsIRequest.LOAD_FRESH_CONNECTION;
[req] = await channelOpenPromise(chan);
Assert.equal(req.protocolVersion, "h2");
let internal = req.QueryInterface(Ci.nsIHttpChannelInternal);
diff --git a/netwerk/test/unit/test_verify_traffic.js b/netwerk/test/unit/test_verify_traffic.js
index be41223642..2b806332c9 100644
--- a/netwerk/test/unit/test_verify_traffic.js
+++ b/netwerk/test/unit/test_verify_traffic.js
@@ -9,6 +9,14 @@
/* import-globals-from head_channels.js */
/* import-globals-from head_servers.js */
+const gDashboard = Cc["@mozilla.org/network/dashboard;1"].getService(
+ Ci.nsIDashboard
+);
+
+const { TestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/TestUtils.sys.mjs"
+);
+
function makeChan(uri) {
let chan = NetUtil.newChannel({
uri,
@@ -106,5 +114,36 @@ add_task(async function test_verify_traffic_for_http2() {
sessionCount = await server.sessionCount();
Assert.equal(sessionCount, 2);
+ // Create another request and trigger the network change event again.
+ // The second network change event is to put the second connection into the
+ // pending list.
+ res = await new Promise(resolve => {
+ // Create a request that takes 8s to finish.
+ let chan = makeChan(`https://localhost:${server.port()}/longDelay`);
+ chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
+
+ Services.obs.notifyObservers(
+ null,
+ "network:link-status-changed",
+ "changed"
+ );
+ });
+
+ Assert.equal(res.status, Cr.NS_OK);
+ Assert.equal(res.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
+
+ async function getSocketCount() {
+ return new Promise(resolve => {
+ gDashboard.requestSockets(function (data) {
+ resolve(data.sockets.length);
+ });
+ });
+ }
+
+ await TestUtils.waitForCondition(async () => {
+ const socketCount = await getSocketCount();
+ return socketCount === 0;
+ }, "Socket count should be 0");
+
await server.stop();
});
diff --git a/netwerk/test/unit/xpcshell.toml b/netwerk/test/unit/xpcshell.toml
index c86a1759e7..a2c09da498 100644
--- a/netwerk/test/unit/xpcshell.toml
+++ b/netwerk/test/unit/xpcshell.toml
@@ -113,6 +113,7 @@ skip-if = [
["test_auth_proxy.js"]
["test_authentication.js"]
+requesttimeoutfactor = 2
["test_authpromptwrapper.js"]
@@ -484,7 +485,6 @@ skip-if = ["os == 'linux' && bits == 64 && !debug"] #Bug 1553353
["test_cookies_partition_counting.js"]
["test_cookies_privatebrowsing.js"]
-skip-if = ["os == 'android' && fission"] # Bug 1888227
["test_cookies_profile_close.js"]
skip-if = ["os == 'android'"] # Bug 1700483
diff --git a/netwerk/wifi/gtest/TestWifiMonitor.cpp b/netwerk/wifi/gtest/TestWifiMonitor.cpp
index f12c5c78ef..37d46c658a 100644
--- a/netwerk/wifi/gtest/TestWifiMonitor.cpp
+++ b/netwerk/wifi/gtest/TestWifiMonitor.cpp
@@ -85,7 +85,7 @@ class TestWifiMonitor : public ::testing::Test {
public:
TestWifiMonitor() {
mObs = mozilla::services::GetObserverService();
- MOZ_ASSERT(mObs);
+ MOZ_RELEASE_ASSERT(mObs);
nsresult rv;
nsCOMPtr<nsINetworkLinkService> nls =
@@ -312,7 +312,7 @@ class TestWifiMonitor : public ::testing::Test {
LOGI(("RunSingleTest: <%s, %s> | requestPolling: %s | shouldPoll: %s",
aTopic, NS_ConvertUTF16toUTF8(aData).get(),
aRequestPolling ? "true" : "false", aShouldPoll ? "true" : "false"));
- MOZ_ASSERT(aShouldPoll || !aRequestPolling);
+ MOZ_RELEASE_ASSERT(aShouldPoll || !aRequestPolling);
CreateObjects();