summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/nsHttpChannel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/protocol/http/nsHttpChannel.cpp')
-rw-r--r--netwerk/protocol/http/nsHttpChannel.cpp135
1 files changed, 100 insertions, 35 deletions
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;