diff options
Diffstat (limited to 'netwerk/protocol')
28 files changed, 315 insertions, 123 deletions
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 |