tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 7682b199e4d2f6333b01b532b6b61008732fc61a
parent 2737b801d7a2b6fe99f2c24256a254521dd72bc2
Author: Serban Stanca <sstanca@mozilla.com>
Date:   Mon, 22 Dec 2025 18:19:12 +0200

Revert "Bug 2006340 - Implement Resource Timing Level 3 interim response timestamps r=necko-reviewers,webidl,smaug,valentin" for causing wpt failures in idlharness.https.any.html.

This reverts commit cc2f0cfc9c13cf2b0a4ad027b8da8ae6bdd689cc.

Diffstat:
Mdom/performance/PerformanceResourceTiming.h | 4----
Mdom/performance/PerformanceTiming.cpp | 55+++++++------------------------------------------------
Mdom/performance/PerformanceTiming.h | 7-------
Mdom/webidl/PerformanceResourceTiming.webidl | 4----
Mnetwerk/base/nsITimedChannel.idl | 4+---
Mnetwerk/ipc/NeckoChannelParams.ipdlh | 2--
Mnetwerk/protocol/http/Http2Session.cpp | 17++---------------
Mnetwerk/protocol/http/Http3Session.cpp | 14--------------
Mnetwerk/protocol/http/HttpBaseChannel.cpp | 7-------
Mnetwerk/protocol/http/HttpChannelChild.cpp | 1-
Mnetwerk/protocol/http/HttpChannelParent.cpp | 2--
Mnetwerk/protocol/http/HttpTransactionParent.cpp | 4----
Mnetwerk/protocol/http/HttpTransactionShell.h | 2--
Mnetwerk/protocol/http/NullHttpChannel.cpp | 8--------
Mnetwerk/protocol/http/TimingStruct.h | 1-
Mnetwerk/protocol/http/nsHttpChannel.cpp | 10----------
Mnetwerk/protocol/http/nsHttpChannel.h | 2--
Mnetwerk/protocol/http/nsHttpTransaction.cpp | 25+++----------------------
Mnetwerk/protocol/http/nsHttpTransaction.h | 2--
Dnetwerk/test/unit/test_http3_interim_response_timing.js | 211-------------------------------------------------------------------------------
Mnetwerk/test/unit/xpcshell.toml | 7-------
Atesting/web-platform/meta/resource-timing/interim-response-times.h2.html.ini | 36++++++++++++++++++++++++++++++++++++
Atesting/web-platform/meta/resource-timing/interim-response-times.html.ini | 36++++++++++++++++++++++++++++++++++++
23 files changed, 85 insertions(+), 376 deletions(-)

diff --git a/dom/performance/PerformanceResourceTiming.h b/dom/performance/PerformanceResourceTiming.h @@ -132,10 +132,6 @@ class PerformanceResourceTiming : public PerformanceEntry { IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(ResponseStart) - IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(FirstInterimResponseStart) - - IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(FinalResponseHeadersStart) - DOMHighResTimeStamp ResponseEnd() const { return mTimingData->ResponseEndHighRes(mPerformance); } diff --git a/dom/performance/PerformanceTiming.cpp b/dom/performance/PerformanceTiming.cpp @@ -182,7 +182,6 @@ PerformanceTimingData::PerformanceTimingData(nsITimedChannel* aChannel, aChannel->GetConnectEnd(&mConnectEnd); aChannel->GetRequestStart(&mRequestStart); aChannel->GetResponseStart(&mResponseStart); - aChannel->GetFinalResponseHeadersStart(&mFinalResponseHeadersStart); aChannel->GetCacheReadStart(&mCacheReadStart); aChannel->GetResponseEnd(&mResponseEnd); aChannel->GetCacheReadEnd(&mCacheReadEnd); @@ -742,62 +741,22 @@ DOMHighResTimeStamp PerformanceTimingData::ResponseStartHighRes( if (!StaticPrefs::dom_enable_performance() || !IsInitialized()) { return mZeroTime; } - - // responseStart is already set correctly in the network layer: - // - For 1xx responses: set on first interim response - // - For final responses: set to the same value as finalResponseHeadersStart - TimeStamp effectiveResponseStart = mResponseStart; - - if (effectiveResponseStart.IsNull() || - (!mCacheReadStart.IsNull() && mCacheReadStart < effectiveResponseStart)) { - effectiveResponseStart = mCacheReadStart; + if (mResponseStart.IsNull() || + (!mCacheReadStart.IsNull() && mCacheReadStart < mResponseStart)) { + mResponseStart = mCacheReadStart; } - if (effectiveResponseStart.IsNull() || - (!mRequestStart.IsNull() && effectiveResponseStart < mRequestStart)) { - effectiveResponseStart = mRequestStart; + if (mResponseStart.IsNull() || + (!mRequestStart.IsNull() && mResponseStart < mRequestStart)) { + mResponseStart = mRequestStart; } - return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, - effectiveResponseStart); + return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, mResponseStart); } DOMTimeMilliSec PerformanceTiming::ResponseStart() { return static_cast<int64_t>(mTimingData->ResponseStartHighRes(mPerformance)); } -DOMHighResTimeStamp PerformanceTimingData::FirstInterimResponseStartHighRes( - Performance* aPerformance) { - MOZ_ASSERT(aPerformance); - - if (!StaticPrefs::dom_enable_performance() || !IsInitialized()) { - return mZeroTime; - } - - // If responseStart < finalResponseHeadersStart, then responseStart was set - // from a 1xx interim response. Otherwise, there was no interim response. - if (!mResponseStart.IsNull() && !mFinalResponseHeadersStart.IsNull() && - mResponseStart < mFinalResponseHeadersStart) { - return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, - mResponseStart); - } - - return 0; // No interim response -} - -DOMHighResTimeStamp PerformanceTimingData::FinalResponseHeadersStartHighRes( - Performance* aPerformance) { - MOZ_ASSERT(aPerformance); - - if (!StaticPrefs::dom_enable_performance() || !IsInitialized()) { - return mZeroTime; - } - if (mFinalResponseHeadersStart.IsNull()) { - return 0; - } - return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, - mFinalResponseHeadersStart); -} - DOMHighResTimeStamp PerformanceTimingData::ResponseEndHighRes( Performance* aPerformance) { MOZ_ASSERT(aPerformance); diff --git a/dom/performance/PerformanceTiming.h b/dom/performance/PerformanceTiming.h @@ -151,10 +151,6 @@ class PerformanceTimingData final : public CacheablePerformanceTimingData { DOMHighResTimeStamp ConnectEndHighRes(Performance* aPerformance); DOMHighResTimeStamp RequestStartHighRes(Performance* aPerformance); DOMHighResTimeStamp ResponseStartHighRes(Performance* aPerformance); - DOMHighResTimeStamp FirstInterimResponseStartHighRes( - Performance* aPerformance); - DOMHighResTimeStamp FinalResponseHeadersStartHighRes( - Performance* aPerformance); DOMHighResTimeStamp ResponseEndHighRes(Performance* aPerformance); DOMHighResTimeStamp ZeroTime() const { return mZeroTime; } @@ -184,7 +180,6 @@ class PerformanceTimingData final : public CacheablePerformanceTimingData { TimeStamp mConnectEnd; TimeStamp mRequestStart; TimeStamp mResponseStart; - TimeStamp mFinalResponseHeadersStart; TimeStamp mCacheReadStart; TimeStamp mResponseEnd; TimeStamp mCacheReadEnd; @@ -417,7 +412,6 @@ struct ParamTraits<mozilla::dom::PerformanceTimingData> { WriteParam(aWriter, aParam.mConnectEnd); WriteParam(aWriter, aParam.mRequestStart); WriteParam(aWriter, aParam.mResponseStart); - WriteParam(aWriter, aParam.mFinalResponseHeadersStart); WriteParam(aWriter, aParam.mCacheReadStart); WriteParam(aWriter, aParam.mResponseEnd); WriteParam(aWriter, aParam.mCacheReadEnd); @@ -453,7 +447,6 @@ struct ParamTraits<mozilla::dom::PerformanceTimingData> { ReadParam(aReader, &aResult->mConnectEnd) && ReadParam(aReader, &aResult->mRequestStart) && ReadParam(aReader, &aResult->mResponseStart) && - ReadParam(aReader, &aResult->mFinalResponseHeadersStart) && ReadParam(aReader, &aResult->mCacheReadStart) && ReadParam(aReader, &aResult->mResponseEnd) && ReadParam(aReader, &aResult->mCacheReadEnd) && diff --git a/dom/webidl/PerformanceResourceTiming.webidl b/dom/webidl/PerformanceResourceTiming.webidl @@ -40,10 +40,6 @@ interface PerformanceResourceTiming : PerformanceEntry [NeedsSubjectPrincipal] readonly attribute DOMHighResTimeStamp requestStart; [NeedsSubjectPrincipal] - readonly attribute DOMHighResTimeStamp finalResponseHeadersStart; - [NeedsSubjectPrincipal] - readonly attribute DOMHighResTimeStamp firstInterimResponseStart; - [NeedsSubjectPrincipal] readonly attribute DOMHighResTimeStamp responseStart; readonly attribute DOMHighResTimeStamp responseEnd; diff --git 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, builtinclass, uuid(8f2c89e7-d654-4b9a-b8f1-3c7e6a9d2f4e)] +[scriptable, builtinclass, uuid(ca63784d-959c-4c3a-9a59-234a2a520de0)] interface nsITimedChannel : nsISupports { // The number of redirects attribute uint8_t redirectCount; @@ -57,7 +57,6 @@ interface nsITimedChannel : nsISupports { [noscript] readonly attribute TimeStamp connectEnd; [noscript] readonly attribute TimeStamp requestStart; [noscript] readonly attribute TimeStamp responseStart; - [noscript] readonly attribute TimeStamp finalResponseHeadersStart; [noscript] readonly attribute TimeStamp responseEnd; // The redirect attributes timings must be writeble, se we can transfer @@ -126,7 +125,6 @@ interface nsITimedChannel : nsISupports { readonly attribute PRTime connectEndTime; readonly attribute PRTime requestStartTime; readonly attribute PRTime responseStartTime; - readonly attribute PRTime finalResponseHeadersStartTime; readonly attribute PRTime responseEndTime; readonly attribute PRTime cacheReadStartTime; readonly attribute PRTime cacheReadEndTime; diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -585,7 +585,6 @@ struct TimingStructArgs { TimeStamp connectEnd; TimeStamp requestStart; TimeStamp responseStart; - TimeStamp finalResponseHeadersStart; TimeStamp responseEnd; TimeStamp transactionPending; }; @@ -599,7 +598,6 @@ struct ResourceTimingStructArgs { TimeStamp connectEnd; TimeStamp requestStart; TimeStamp responseStart; - TimeStamp finalResponseHeadersStart; TimeStamp responseEnd; TimeStamp fetchStart; TimeStamp redirectStart; diff --git a/netwerk/protocol/http/Http2Session.cpp b/netwerk/protocol/http/Http2Session.cpp @@ -1703,21 +1703,8 @@ nsresult Http2Session::ResponseHeadersComplete() { } // allow more headers in the case of 1xx - if (didFirstSetAllRecvd) { - RefPtr<nsAHttpTransaction> trans = mInputFrameDataStream->Transaction(); - nsHttpTransaction* httpTrans = - trans ? trans->QueryHttpTransaction() : nullptr; - auto now = TimeStamp::Now(); - if (httpTrans) { - // Set responseStart only the first time - httpTrans->SetResponseStart(now, true); - } - - if ((httpResponseCode / 100) == 1) { - mInputFrameDataStream->UnsetAllHeadersReceived(); - } else if (httpTrans) { // For non interim responses - httpTrans->SetFinalResponseHeadersStart(now, true); - } + if (((httpResponseCode / 100) == 1) && didFirstSetAllRecvd) { + mInputFrameDataStream->UnsetAllHeadersReceived(); } ChangeDownstreamState(PROCESSING_COMPLETE_HEADERS); diff --git a/netwerk/protocol/http/Http3Session.cpp b/netwerk/protocol/http/Http3Session.cpp @@ -555,20 +555,6 @@ nsresult Http3Session::ProcessEvents() { stream->SetResponseHeaders(data, event.header_ready.fin, event.header_ready.interim); - // Capture response timing - RefPtr<Http3Stream> http3Stream = stream->GetHttp3Stream(); - MOZ_RELEASE_ASSERT(http3Stream, "This must be a Http3Stream"); - RefPtr<nsAHttpTransaction> trans = http3Stream->Transaction(); - nsHttpTransaction* httpTrans = - trans ? trans->QueryHttpTransaction() : nullptr; - if (httpTrans) { - auto now = TimeStamp::Now(); - httpTrans->SetResponseStart(now, true); // Won't overwrite if set - if (!event.header_ready.interim) { - httpTrans->SetFinalResponseHeadersStart(now, true); - } - } - rv = ProcessTransactionRead(stream); if (NS_FAILED(rv)) { diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -5929,12 +5929,6 @@ HttpBaseChannel::GetResponseStart(TimeStamp* _retval) { } NS_IMETHODIMP -HttpBaseChannel::GetFinalResponseHeadersStart(TimeStamp* _retval) { - *_retval = mTransactionTimings.finalResponseHeadersStart; - return NS_OK; -} - -NS_IMETHODIMP HttpBaseChannel::GetResponseEnd(TimeStamp* _retval) { *_retval = mTransactionTimings.responseEnd; return NS_OK; @@ -6001,7 +5995,6 @@ IMPL_TIMING_ATTR(SecureConnectionStart) IMPL_TIMING_ATTR(ConnectEnd) IMPL_TIMING_ATTR(RequestStart) IMPL_TIMING_ATTR(ResponseStart) -IMPL_TIMING_ATTR(FinalResponseHeadersStart) IMPL_TIMING_ATTR(ResponseEnd) IMPL_TIMING_ATTR(CacheReadStart) IMPL_TIMING_ATTR(CacheReadEnd) diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp @@ -367,7 +367,6 @@ static void ResourceTimingStructArgsToTimingsStruct( aTimings.connectEnd = aArgs.connectEnd(); aTimings.requestStart = aArgs.requestStart(); aTimings.responseStart = aArgs.responseStart(); - aTimings.finalResponseHeadersStart = aArgs.finalResponseHeadersStart(); aTimings.responseEnd = aArgs.responseEnd(); aTimings.transactionPending = aArgs.transactionPending(); } diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp @@ -1094,8 +1094,6 @@ static ResourceTimingStructArgs GetTimingAttributes(HttpBaseChannel* aChannel) { args.requestStart() = timeStamp; aChannel->GetResponseStart(&timeStamp); args.responseStart() = timeStamp; - aChannel->GetFinalResponseHeadersStart(&timeStamp); - args.finalResponseHeadersStart() = timeStamp; aChannel->GetResponseEnd(&timeStamp); args.responseEnd() = timeStamp; aChannel->GetAsyncOpen(&timeStamp); diff --git a/netwerk/protocol/http/HttpTransactionParent.cpp b/netwerk/protocol/http/HttpTransactionParent.cpp @@ -317,10 +317,6 @@ mozilla::TimeStamp HttpTransactionParent::GetResponseStart() { return mTimings.responseStart; } -mozilla::TimeStamp HttpTransactionParent::GetFinalResponseHeadersStart() { - return mTimings.finalResponseHeadersStart; -} - mozilla::TimeStamp HttpTransactionParent::GetResponseEnd() { return mTimings.responseEnd; } diff --git a/netwerk/protocol/http/HttpTransactionShell.h b/netwerk/protocol/http/HttpTransactionShell.h @@ -134,7 +134,6 @@ class HttpTransactionShell : public nsISupports { virtual mozilla::TimeStamp GetConnectEnd() = 0; virtual mozilla::TimeStamp GetRequestStart() = 0; virtual mozilla::TimeStamp GetResponseStart() = 0; - virtual mozilla::TimeStamp GetFinalResponseHeadersStart() = 0; virtual mozilla::TimeStamp GetResponseEnd() = 0; virtual void SetDomainLookupStart(mozilla::TimeStamp timeStamp, @@ -217,7 +216,6 @@ class HttpTransactionShell : public nsISupports { virtual mozilla::TimeStamp GetConnectEnd() override; \ virtual mozilla::TimeStamp GetRequestStart() override; \ virtual mozilla::TimeStamp GetResponseStart() override; \ - virtual mozilla::TimeStamp GetFinalResponseHeadersStart() override; \ virtual mozilla::TimeStamp GetResponseEnd() override; \ virtual void SetDomainLookupStart(mozilla::TimeStamp timeStamp, \ bool onlyIfNull = false) override; \ diff --git a/netwerk/protocol/http/NullHttpChannel.cpp b/netwerk/protocol/http/NullHttpChannel.cpp @@ -671,13 +671,6 @@ NullHttpChannel::GetResponseStart(mozilla::TimeStamp* aResponseStart) { } NS_IMETHODIMP -NullHttpChannel::GetFinalResponseHeadersStart( - mozilla::TimeStamp* aFinalResponseHeadersStart) { - *aFinalResponseHeadersStart = mAsyncOpenTime; - return NS_OK; -} - -NS_IMETHODIMP NullHttpChannel::GetResponseEnd(mozilla::TimeStamp* aResponseEnd) { *aResponseEnd = mAsyncOpenTime; return NS_OK; @@ -892,7 +885,6 @@ IMPL_TIMING_ATTR(SecureConnectionStart) IMPL_TIMING_ATTR(ConnectEnd) IMPL_TIMING_ATTR(RequestStart) IMPL_TIMING_ATTR(ResponseStart) -IMPL_TIMING_ATTR(FinalResponseHeadersStart) IMPL_TIMING_ATTR(ResponseEnd) IMPL_TIMING_ATTR(CacheReadStart) IMPL_TIMING_ATTR(CacheReadEnd) diff --git a/netwerk/protocol/http/TimingStruct.h b/netwerk/protocol/http/TimingStruct.h @@ -20,7 +20,6 @@ struct TimingStruct { TimeStamp connectEnd; TimeStamp requestStart; TimeStamp responseStart; - TimeStamp finalResponseHeadersStart; TimeStamp responseEnd; TimeStamp transactionPending; }; diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp @@ -8538,16 +8538,6 @@ nsHttpChannel::GetResponseStart(TimeStamp* _retval) { } NS_IMETHODIMP -nsHttpChannel::GetFinalResponseHeadersStart(TimeStamp* _retval) { - if (mTransaction) { - *_retval = mTransaction->GetFinalResponseHeadersStart(); - } else { - *_retval = mTransactionTimings.finalResponseHeadersStart; - } - return NS_OK; -} - -NS_IMETHODIMP nsHttpChannel::GetResponseEnd(TimeStamp* _retval) { if (mTransaction) { *_retval = mTransaction->GetResponseEnd(); diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h @@ -180,8 +180,6 @@ class nsHttpChannel final : public HttpBaseChannel, NS_IMETHOD GetConnectEnd(mozilla::TimeStamp* aConnectEnd) override; NS_IMETHOD GetRequestStart(mozilla::TimeStamp* aRequestStart) override; NS_IMETHOD GetResponseStart(mozilla::TimeStamp* aResponseStart) override; - NS_IMETHOD GetFinalResponseHeadersStart( - mozilla::TimeStamp* aFinalResponseHeadersStart) override; NS_IMETHOD GetResponseEnd(mozilla::TimeStamp* aResponseEnd) override; NS_IMETHOD GetTransactionPending( diff --git a/netwerk/protocol/http/nsHttpTransaction.cpp b/netwerk/protocol/http/nsHttpTransaction.cpp @@ -814,6 +814,9 @@ nsresult nsHttpTransaction::WritePipeSegment(nsIOutputStream* stream, if (trans->mTransactionDone) return NS_BASE_STREAM_CLOSED; // stop iterating + // Set the timestamp to Now(), only if it null + trans->SetResponseStart(TimeStamp::Now(), true); + // Bug 1153929 - add checks to fix windows crash MOZ_ASSERT(trans->mWriter); if (!trans->mWriter) { @@ -2071,14 +2074,6 @@ nsresult nsHttpTransaction::ParseLineSegment(char* segment, uint32_t len) { mLineBuf.Truncate(); // discard this response if it is a 100 continue or other 1xx status. uint16_t status = mResponseHead->Status(); - - // Capture timing for interim (1xx) vs final responses - auto now = TimeStamp::Now(); - SetResponseStart(now, true); // Won't overwrite if already set from 1xx - if (status / 100 != 1) { - SetFinalResponseHeadersStart(now, true); - } - if (status == 103 && (StaticPrefs::network_early_hints_over_http_v1_1_enabled() || mResponseHead->Version() != HttpVersion::v1_1)) { @@ -2908,15 +2903,6 @@ void nsHttpTransaction::SetResponseEnd(mozilla::TimeStamp timeStamp, mTimings.responseEnd = timeStamp; } -void nsHttpTransaction::SetFinalResponseHeadersStart( - mozilla::TimeStamp timeStamp, bool onlyIfNull) { - mozilla::MutexAutoLock lock(mLock); - if (onlyIfNull && !mTimings.finalResponseHeadersStart.IsNull()) { - return; - } - mTimings.finalResponseHeadersStart = timeStamp; -} - mozilla::TimeStamp nsHttpTransaction::GetDomainLookupStart() { mozilla::MutexAutoLock lock(mLock); return mTimings.domainLookupStart; @@ -2962,11 +2948,6 @@ mozilla::TimeStamp nsHttpTransaction::GetResponseEnd() { return mTimings.responseEnd; } -mozilla::TimeStamp nsHttpTransaction::GetFinalResponseHeadersStart() { - mozilla::MutexAutoLock lock(mLock); - return mTimings.finalResponseHeadersStart; -} - //----------------------------------------------------------------------------- // nsHttpTransaction deletion event //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/nsHttpTransaction.h b/netwerk/protocol/http/nsHttpTransaction.h @@ -154,8 +154,6 @@ class nsHttpTransaction final : public nsAHttpTransaction, void SetConnectEnd(mozilla::TimeStamp timeStamp, bool onlyIfNull = false); void SetRequestStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false); void SetResponseStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false); - void SetFinalResponseHeadersStart(mozilla::TimeStamp timeStamp, - bool onlyIfNull = false); void SetResponseEnd(mozilla::TimeStamp timeStamp, bool onlyIfNull = false); [[nodiscard]] bool Do0RTT() override; diff --git a/netwerk/test/unit/test_http3_interim_response_timing.js b/netwerk/test/unit/test_http3_interim_response_timing.js @@ -1,211 +0,0 @@ -/* 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/. */ - -"use strict"; - -// Test Resource Timing Level 3 interim response timestamps with HTTP/3 -// https://www.w3.org/TR/resource-timing/#interim-response-times - -var { setTimeout } = ChromeUtils.importESModule( - "resource://gre/modules/Timer.sys.mjs" -); - -const earlyhintspath = "/103_response"; - -add_setup(async function () { - await http3_setup_tests("h3"); -}); - -function makeChan(url) { - let chan = NetUtil.newChannel({ - uri: url, - loadUsingSystemPrincipal: true, - contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT, - }).QueryInterface(Ci.nsIHttpChannel); - return chan; -} - -function channelOpenPromise(chan, flags) { - return new Promise(resolve => { - function finish(req, buffer) { - resolve([req, buffer]); - } - chan.asyncOpen(new ChannelListener(finish, null, flags)); - }); -} - -// Test HTTP/3 request without interim response (no 103 Early Hints) -add_task(async function test_http3_no_interim_response() { - Services.obs.notifyObservers(null, "net:prune-all-connections"); - // eslint-disable-next-line mozilla/no-arbitrary-setTimeout - await new Promise(resolve => setTimeout(resolve, 1000)); - - let chan = makeChan(`https://foo.example.com`); - let [req] = await channelOpenPromise(chan); - - // Verify it's HTTP/3 - let httpVersion = ""; - try { - httpVersion = req.protocolVersion; - } catch (e) {} - Assert.equal(httpVersion, "h3", "Request should use HTTP/3"); - - let timing = req.QueryInterface(Ci.nsITimedChannel); - - // When there's no interim response: - // - firstInterimResponseStart should be 0 (computed) - // - responseStart should equal finalResponseHeadersStart - - // Compute firstInterimResponseStart the same way Performance API does - let firstInterimResponseStart = 0; - if ( - timing.responseStartTime > 0 && - timing.finalResponseHeadersStartTime > 0 && - timing.responseStartTime < timing.finalResponseHeadersStartTime - ) { - firstInterimResponseStart = timing.responseStartTime; - } - - Assert.equal( - firstInterimResponseStart, - 0, - "firstInterimResponseStart should be 0 when no interim response" - ); - - Assert.greater(timing.responseStartTime, 0, "responseStart should be set"); - Assert.greater( - timing.finalResponseHeadersStartTime, - 0, - "finalResponseHeadersStart should be set" - ); - - // responseStart should approximately equal finalResponseHeadersStart - // (they're set to the same TimeStamp in the code) - let timeDiff = Math.abs( - timing.responseStartTime - timing.finalResponseHeadersStartTime - ); - Assert.less( - timeDiff, - 10, - "responseStart and finalResponseHeadersStart should be approximately equal when no interim response" - ); -}); - -// Test HTTP/3 request with interim response (103 Early Hints) -add_task(async function test_http3_with_interim_response() { - Services.obs.notifyObservers(null, "net:prune-all-connections"); - // eslint-disable-next-line mozilla/no-arbitrary-setTimeout - await new Promise(resolve => setTimeout(resolve, 1000)); - - let chan = makeChan(`https://foo.example.com${earlyhintspath}`); - // Request 103 Early Hints - chan.setRequestHeader( - "link-to-set", - "</style.css>; rel=preload; as=style", - false - ); - - let [req] = await channelOpenPromise(chan); - - // Verify it's HTTP/3 - let httpVersion = ""; - try { - httpVersion = req.protocolVersion; - } catch (e) {} - Assert.equal(httpVersion, "h3", "Request should use HTTP/3"); - - let timing = req.QueryInterface(Ci.nsITimedChannel); - - // When there's an interim response (103 Early Hints): - // - firstInterimResponseStart should be > 0 (computed) - // - responseStart should equal firstInterimResponseStart - // - finalResponseHeadersStart should be >= firstInterimResponseStart - - // Compute firstInterimResponseStart the same way Performance API does - let firstInterimResponseStart = 0; - if ( - timing.responseStartTime > 0 && - timing.finalResponseHeadersStartTime > 0 && - timing.responseStartTime < timing.finalResponseHeadersStartTime - ) { - firstInterimResponseStart = timing.responseStartTime; - } - - Assert.greater( - firstInterimResponseStart, - 0, - "firstInterimResponseStart should be set when interim response received" - ); - - Assert.greater(timing.responseStartTime, 0, "responseStart should be set"); - Assert.greater( - timing.finalResponseHeadersStartTime, - 0, - "finalResponseHeadersStart should be set" - ); - - // responseStart should equal firstInterimResponseStart (computed from responseStart) - Assert.equal( - timing.responseStartTime, - firstInterimResponseStart, - "responseStart should equal firstInterimResponseStart when interim response received" - ); - - // Timing order should be: firstInterimResponseStart <= finalResponseHeadersStart - Assert.lessOrEqual( - firstInterimResponseStart, - timing.finalResponseHeadersStartTime, - "firstInterimResponseStart should be before or equal to finalResponseHeadersStart" - ); -}); - -// Test timing ordering with HTTP/3 and interim response -add_task(async function test_http3_timing_order() { - Services.obs.notifyObservers(null, "net:prune-all-connections"); - // eslint-disable-next-line mozilla/no-arbitrary-setTimeout - await new Promise(resolve => setTimeout(resolve, 1000)); - - let chan = makeChan(`https://foo.example.com${earlyhintspath}`); - chan.setRequestHeader( - "link-to-set", - "</img.png>; rel=preload; as=image", - false - ); - - let [req] = await channelOpenPromise(chan); - let timing = req.QueryInterface(Ci.nsITimedChannel); - - // Compute firstInterimResponseStart - let firstInterimResponseStart = 0; - if ( - timing.responseStartTime > 0 && - timing.finalResponseHeadersStartTime > 0 && - timing.responseStartTime < timing.finalResponseHeadersStartTime - ) { - firstInterimResponseStart = timing.responseStartTime; - } - - // Verify complete timing order: - // requestStart <= firstInterimResponseStart <= finalResponseHeadersStart <= responseEnd - Assert.greater(timing.requestStartTime, 0, "requestStart should be set"); - Assert.lessOrEqual( - timing.requestStartTime, - firstInterimResponseStart, - "requestStart should be before or equal to firstInterimResponseStart" - ); - Assert.lessOrEqual( - firstInterimResponseStart, - timing.finalResponseHeadersStartTime, - "firstInterimResponseStart should be before or equal to finalResponseHeadersStart" - ); - Assert.lessOrEqual( - timing.finalResponseHeadersStartTime, - timing.responseEndTime, - "finalResponseHeadersStart should be before or equal to responseEnd" - ); -}); - -registerCleanupFunction(async () => { - http3_clear_prefs(); -}); diff --git a/netwerk/test/unit/xpcshell.toml b/netwerk/test/unit/xpcshell.toml @@ -871,13 +871,6 @@ skip-if = [ "os == 'win' && os_version == '11.26100' && arch == 'x86_64' && msix", # Bug 1807931 ] -["test_http3_interim_response_timing.js"] -run-sequentially = ["true"] # node server exceptions dont replay well -skip-if = [ - "os == 'android'", # H3 servers don't work well on Android - "msix", # H3 servers don't work well on MSIX -] - ["test_http3_kyber.js"] skip-if = [ "os == 'android' && os_version == '14' && arch == 'x86_64'", diff --git a/testing/web-platform/meta/resource-timing/interim-response-times.h2.html.ini b/testing/web-platform/meta/resource-timing/interim-response-times.h2.html.ini @@ -0,0 +1,36 @@ +[interim-response-times.h2.html] + [Fetch from same-origin with early hints, with 100 response] + expected: FAIL + + [Fetch from cross-origin with early hints, with 100 response] + expected: FAIL + + [Fetch from cross-origin-with-TAO with early hints, with 100 response] + expected: FAIL + + [Fetch from same-origin with early hints, without 100 response] + expected: FAIL + + [Fetch from cross-origin with early hints, without 100 response] + expected: FAIL + + [Fetch from cross-origin-with-TAO with early hints, without 100 response] + expected: FAIL + + [Fetch from same-origin without early hints, with 100 response] + expected: FAIL + + [Fetch from cross-origin without early hints, with 100 response] + expected: FAIL + + [Fetch from cross-origin-with-TAO without early hints, with 100 response] + expected: FAIL + + [Fetch from same-origin without early hints, without 100 response] + expected: FAIL + + [Fetch from cross-origin without early hints, without 100 response] + expected: FAIL + + [Fetch from cross-origin-with-TAO without early hints, without 100 response] + expected: FAIL diff --git a/testing/web-platform/meta/resource-timing/interim-response-times.html.ini b/testing/web-platform/meta/resource-timing/interim-response-times.html.ini @@ -0,0 +1,36 @@ +[interim-response-times.html] + [Fetch from same-origin with early hints, with 100 response] + expected: FAIL + + [Fetch from cross-origin with early hints, with 100 response] + expected: FAIL + + [Fetch from cross-origin-with-TAO with early hints, with 100 response] + expected: FAIL + + [Fetch from same-origin with early hints, without 100 response] + expected: FAIL + + [Fetch from cross-origin with early hints, without 100 response] + expected: FAIL + + [Fetch from cross-origin-with-TAO with early hints, without 100 response] + expected: FAIL + + [Fetch from same-origin without early hints, with 100 response] + expected: FAIL + + [Fetch from cross-origin without early hints, with 100 response] + expected: FAIL + + [Fetch from cross-origin-with-TAO without early hints, with 100 response] + expected: FAIL + + [Fetch from same-origin without early hints, without 100 response] + expected: FAIL + + [Fetch from cross-origin without early hints, without 100 response] + expected: FAIL + + [Fetch from cross-origin-with-TAO without early hints, without 100 response] + expected: FAIL