tor-browser

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

commit 11f7ea81cf048c290e5b97c2950d8cb9c6bd94e4
parent 73e21f505e8f0930fecaf4045915396b52b1093f
Author: Kershaw Chang <kershaw@mozilla.com>
Date:   Fri, 17 Oct 2025 07:29:16 +0000

Bug 1994648 - Run current HTTP/2 tests with HTTP/3 proxy, r=necko-reviewers,valentin

Differential Revision: https://phabricator.services.mozilla.com/D268838

Diffstat:
Mnetwerk/protocol/http/Http2Stream.cpp | 6++++++
Mnetwerk/protocol/http/Http3Session.cpp | 6++----
Mnetwerk/protocol/http/Http3Session.h | 6++++++
Mnetwerk/test/unit/http2_test_common.js | 144+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Anetwerk/test/unit/test_http2_with_http3_proxy.js | 344+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mnetwerk/test/unit/xpcshell.toml | 10++++++++++
6 files changed, 457 insertions(+), 59 deletions(-)

diff --git a/netwerk/protocol/http/Http2Stream.cpp b/netwerk/protocol/http/Http2Stream.cpp @@ -33,6 +33,12 @@ Http2Stream::Http2Stream(nsAHttpTransaction* httpTransaction, Http2Stream::~Http2Stream() {} void Http2Stream::CloseStream(nsresult reason) { + if (reason == NS_ERROR_NET_RESET) { + // If we got NS_ERROR_NET_RESET, the transaction will be retried. Keep the + // Alt-Svc in the connection info. Dropping it could trigger an + // unintended proxy connection fallback. + mTransaction->DoNotRemoveAltSvc(); + } mTransaction->Close(reason); mSession = nullptr; mClosed = true; diff --git a/netwerk/protocol/http/Http3Session.cpp b/netwerk/protocol/http/Http3Session.cpp @@ -2163,9 +2163,7 @@ void Http3Session::CloseStreamInternal(Http3StreamBase* aStream, // Close(NS_OK) implies that the NeqoHttp3Conn will be closed, so we can only // do this when there is no Http3Steeam, WebTransportSession and // WebTransportStream. - if ((mShouldClose || mGoawayReceived) && - (!mStreamTransactionHash.Count() && mWebTransportSessions.IsEmpty() && - mWebTransportStreams.IsEmpty() && mTunnelStreams.IsEmpty())) { + if ((mShouldClose || mGoawayReceived) && HasNoActiveStreams()) { MOZ_ASSERT(!IsClosing()); Close(NS_OK); } @@ -2240,7 +2238,7 @@ void Http3Session::DontReuse() { } mShouldClose = true; - if (!mStreamTransactionHash.Count()) { + if (HasNoActiveStreams()) { // This is a temporary workaround and should be fixed properly in Happy // Eyeballs project. We should not exclude this domain if // Http3Session::DontReuse is called from diff --git a/netwerk/protocol/http/Http3Session.h b/netwerk/protocol/http/Http3Session.h @@ -470,6 +470,12 @@ class Http3Session final : public Http3SessionBase, // are exchanged. void FinishNegotiation(ExtendedConnectKind aKind, bool aSuccess); + inline bool HasNoActiveStreams() const { + return mStreamTransactionHash.Count() == 0 && + mWebTransportSessions.IsEmpty() && mWebTransportStreams.IsEmpty() && + mTunnelStreams.IsEmpty(); + } + nsTArray<RefPtr<Http3StreamBase>> mWebTransportSessions; nsTArray<RefPtr<Http3StreamBase>> mWebTransportStreams; nsTArray<RefPtr<Http3StreamBase>> mTunnelStreams; diff --git a/netwerk/test/unit/http2_test_common.js b/netwerk/test/unit/http2_test_common.js @@ -64,6 +64,14 @@ Http2CheckListener.prototype = { } Assert.ok(request instanceof Ci.nsIHttpChannel); + if (this.noResponseStatus) { + Assert.throws( + () => request.responseStatus, + /NS_ERROR_NOT_AVAILABLE/, + "getting response status should throw" + ); + return; + } Assert.equal(request.requestSucceeded, this.shouldSucceed); if (this.shouldSucceed) { Assert.equal(request.responseStatus, 200); @@ -314,8 +322,8 @@ async function test_http2_blocking_download(serverPort) { } // Make sure we make a HTTP2 connection and both us and the server mark it as such -async function test_http2_basic(serverPort) { - var chan = makeHTTPChannel(`https://localhost:${serverPort}/`); +async function test_http2_basic(serverPort, origin = "localhost") { + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/`); var p = new Promise(resolve => { var listener = new Http2CheckListener(); listener.finish = resolve; @@ -324,9 +332,12 @@ async function test_http2_basic(serverPort) { return p; } -async function test_http2_basic_unblocked_dep(serverPort) { +async function test_http2_basic_unblocked_dep( + serverPort, + origin = "localhost" +) { var chan = makeHTTPChannel( - `https://localhost:${serverPort}/basic_unblocked_dep` + `https://${origin}:${serverPort}/basic_unblocked_dep` ); var cos = chan.QueryInterface(Ci.nsIClassOfService); cos.addClassFlags(Ci.nsIClassOfService.Unblocked); @@ -338,8 +349,8 @@ async function test_http2_basic_unblocked_dep(serverPort) { } // make sure we don't use h2 when disallowed -async function test_http2_nospdy(serverPort) { - var chan = makeHTTPChannel(`https://localhost:${serverPort}/`); +async function test_http2_nospdy(serverPort, origin = "localhost") { + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/`); return new Promise(resolve => { var listener = new Http2CheckListener(); listener.finish = resolve; @@ -362,10 +373,10 @@ function checkXhr(xhr, finish) { } // Fires off an XHR request over h2 -async function test_http2_xhr(serverPort) { +async function test_http2_xhr(serverPort, origin = "localhost") { return new Promise(resolve => { var req = new XMLHttpRequest(); - req.open("GET", `https://localhost:${serverPort}/`, true); + req.open("GET", `https://${origin}:${serverPort}/`, true); req.addEventListener("readystatechange", function () { checkXhr(req, resolve); }); @@ -401,7 +412,11 @@ Http2ConcurrentListener.prototype.onStopRequest = function (request) { } }; -async function test_http2_concurrent(concurrent_channels, serverPort) { +async function test_http2_concurrent( + concurrent_channels, + serverPort, + origin = "localhost" +) { var p = new Promise(resolve => { var concurrent_listener = new Http2ConcurrentListener(); concurrent_listener.finish = resolve; @@ -413,7 +428,7 @@ async function test_http2_concurrent(concurrent_channels, serverPort) { for (var i = 0; i < concurrent_listener.target; i++) { concurrent_channels[i] = makeHTTPChannel( - `https://localhost:${serverPort}/750ms` + `https://${origin}:${serverPort}/750ms` ); concurrent_channels[i].loadFlags = Ci.nsIRequest.LOAD_BYPASS_CACHE; concurrent_channels[i].asyncOpen(concurrent_listener); @@ -422,7 +437,11 @@ async function test_http2_concurrent(concurrent_channels, serverPort) { return p; } -async function test_http2_concurrent_post(concurrent_channels, serverPort) { +async function test_http2_concurrent_post( + concurrent_channels, + serverPort, + origin = "localhost" +) { return new Promise(resolve => { var concurrent_listener = new Http2ConcurrentListener(); concurrent_listener.finish = resolve; @@ -435,7 +454,7 @@ async function test_http2_concurrent_post(concurrent_channels, serverPort) { for (var i = 0; i < concurrent_listener.target; i++) { concurrent_channels[i] = makeHTTPChannel( - `https://localhost:${serverPort}/750msPost` + `https://${origin}:${serverPort}/750msPost` ); concurrent_channels[i].loadFlags = Ci.nsIRequest.LOAD_BYPASS_CACHE; var stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance( @@ -473,8 +492,8 @@ async function test_http2_multiplex(serverPort) { } // Test to make sure we gateway non-standard headers properly -async function test_http2_header(serverPort) { - let chan = makeHTTPChannel(`https://localhost:${serverPort}/header`); +async function test_http2_header(serverPort, origin = "localhost") { + let chan = makeHTTPChannel(`https://${origin}:${serverPort}/header`); let hvalue = "Headers are fun"; chan.setRequestHeader("X-Test-Header", hvalue, false); return new Promise(resolve => { @@ -489,22 +508,26 @@ async function test_http2_header(serverPort) { } // Test to make sure headers with invalid characters in the name are rejected -async function test_http2_invalid_response_header(serverPort, invalid_kind) { +async function test_http2_invalid_response_header( + serverPort, + invalid_kind, + origin = "localhost" +) { return new Promise(resolve => { var listener = new Http2CheckListener(); listener.finish = resolve; listener.shouldSucceed = false; var chan = makeHTTPChannel( - `https://localhost:${serverPort}/invalid_response_header/${invalid_kind}` + `https://${origin}:${serverPort}/invalid_response_header/${invalid_kind}` ); chan.asyncOpen(listener); }); } // Test to make sure cookies are split into separate fields before compression -async function test_http2_cookie_crumbling(serverPort) { +async function test_http2_cookie_crumbling(serverPort, origin = "localhost") { var chan = makeHTTPChannel( - `https://localhost:${serverPort}/cookie_crumbling` + `https://${origin}:${serverPort}/cookie_crumbling` ); var cookiesSent = ["a=b", "c=d01234567890123456789", "e=f"].sort(); chan.setRequestHeader("Cookie", cookiesSent.join("; "), false); @@ -532,8 +555,8 @@ async function test_http2_cookie_crumbling(serverPort) { // this is a basic test where the server sends a simple document with 2 header // blocks. bug 1027364 -async function test_http2_doubleheader(serverPort) { - var chan = makeHTTPChannel(`https://localhost:${serverPort}/doubleheader`); +async function test_http2_doubleheader(serverPort, origin = "localhost") { + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/doubleheader`); return new Promise(resolve => { var listener = new Http2CheckListener(); listener.finish = resolve; @@ -542,8 +565,8 @@ async function test_http2_doubleheader(serverPort) { } // Make sure we handle GETs that cover more than 2 frames properly -async function test_http2_big(serverPort) { - var chan = makeHTTPChannel(`https://localhost:${serverPort}/big`); +async function test_http2_big(serverPort, origin = "localhost") { + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/big`); return new Promise(resolve => { var listener = new Http2BigListener(); listener.finish = resolve; @@ -551,8 +574,8 @@ async function test_http2_big(serverPort) { }); } -async function test_http2_huge_suspended(serverPort) { - var chan = makeHTTPChannel(`https://localhost:${serverPort}/huge`); +async function test_http2_huge_suspended(serverPort, origin = "localhost") { + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/huge`); return new Promise(resolve => { var listener = new Http2HugeSuspendedListener(); listener.finish = resolve; @@ -578,8 +601,8 @@ function do_post(content, chan, listener, method) { } // Make sure we can do a simple POST -async function test_http2_post(serverPort) { - var chan = makeHTTPChannel(`https://localhost:${serverPort}/post`); +async function test_http2_post(serverPort, origin = "localhost") { + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/post`); var p = new Promise(resolve => { var listener = new Http2PostListener(md5s[0]); listener.finish = resolve; @@ -588,8 +611,8 @@ async function test_http2_post(serverPort) { return p; } -async function test_http2_empty_post(serverPort) { - var chan = makeHTTPChannel(`https://localhost:${serverPort}/post`); +async function test_http2_empty_post(serverPort, origin = "localhost") { + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/post`); var p = new Promise(resolve => { var listener = new Http2PostListener("0"); listener.finish = resolve; @@ -599,8 +622,8 @@ async function test_http2_empty_post(serverPort) { } // Make sure we can do a simple PATCH -async function test_http2_patch(serverPort) { - var chan = makeHTTPChannel(`https://localhost:${serverPort}/patch`); +async function test_http2_patch(serverPort, origin = "localhost") { + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/patch`); return new Promise(resolve => { var listener = new Http2PostListener(md5s[0]); listener.finish = resolve; @@ -609,8 +632,8 @@ async function test_http2_patch(serverPort) { } // Make sure we can do a POST that covers more than 2 frames -async function test_http2_post_big(serverPort) { - var chan = makeHTTPChannel(`https://localhost:${serverPort}/post`); +async function test_http2_post_big(serverPort, origin = "localhost") { + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/post`); return new Promise(resolve => { var listener = new Http2PostListener(md5s[1]); listener.finish = resolve; @@ -764,13 +787,13 @@ WrongSuiteListener.prototype.onStopRequest = function (request, status) { // test that we use h1 without the mandatory cipher suite available when // offering at most tls1.2 -async function test_http2_wrongsuite_tls12(serverPort) { +async function test_http2_wrongsuite_tls12(serverPort, origin = "localhost") { Services.prefs.setBoolPref( "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256", false ); Services.prefs.setIntPref("security.tls.version.max", 3); - var chan = makeHTTPChannel(`https://localhost:${serverPort}/wrongsuite`); + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/wrongsuite`); chan.loadFlags = Ci.nsIRequest.LOAD_FRESH_CONNECTION | Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI; @@ -783,12 +806,12 @@ async function test_http2_wrongsuite_tls12(serverPort) { // test that we use h2 when offering tls1.3 or higher regardless of if the // mandatory cipher suite is available -async function test_http2_wrongsuite_tls13(serverPort) { +async function test_http2_wrongsuite_tls13(serverPort, origin = "localhost") { Services.prefs.setBoolPref( "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256", false ); - var chan = makeHTTPChannel(`https://localhost:${serverPort}/wrongsuite`); + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/wrongsuite`); chan.loadFlags = Ci.nsIRequest.LOAD_FRESH_CONNECTION | Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI; @@ -800,9 +823,9 @@ async function test_http2_wrongsuite_tls13(serverPort) { }); } -async function test_http2_h11required_stream(serverPort) { +async function test_http2_h11required_stream(serverPort, origin = "localhost") { var chan = makeHTTPChannel( - `https://localhost:${serverPort}/h11required_stream` + `https://${origin}:${serverPort}/h11required_stream` ); return new Promise(resolve => { var listener = new Http2CheckListener(); @@ -829,9 +852,12 @@ H11RequiredSessionListener.prototype.onStopRequest = function (request) { this.finish({ httpProxyConnectResponseCode }); }; -async function test_http2_h11required_session(serverPort) { +async function test_http2_h11required_session( + serverPort, + origin = "localhost" +) { var chan = makeHTTPChannel( - `https://localhost:${serverPort}/h11required_session` + `https://${origin}:${serverPort}/h11required_session` ); return new Promise(resolve => { var listener = new H11RequiredSessionListener(); @@ -841,8 +867,8 @@ async function test_http2_h11required_session(serverPort) { }); } -async function test_http2_retry_rst(serverPort) { - var chan = makeHTTPChannel(`https://localhost:${serverPort}/rstonce`); +async function test_http2_retry_rst(serverPort, origin = "localhost") { + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/rstonce`); return new Promise(resolve => { var listener = new Http2CheckListener(); listener.finish = resolve; @@ -852,16 +878,18 @@ async function test_http2_retry_rst(serverPort) { async function test_http2_continuations_over_max_response_limit( loadGroup, - serverPort + serverPort, + origin = "localhost" ) { var chan = makeHTTPChannel( - `https://localhost:${serverPort}/hugecontinuedheaders?size=385` + `https://${origin}:${serverPort}/hugecontinuedheaders?size=385` ); chan.loadGroup = loadGroup; return new Promise(resolve => { var listener = new Http2CheckListener(); listener.finish = resolve; listener.shouldSucceed = false; + listener.noResponseStatus = true; chan.asyncOpen(listener); }); } @@ -892,7 +920,7 @@ Http2IllegalHpackListener.prototype.shouldGoAway = false; Http2IllegalHpackListener.prototype.onStopRequest = function () { var chan = makeHTTPChannel( - `https://localhost:${this.serverPort}/illegalhpack_validate` + `https://${this.origin}:${this.serverPort}/illegalhpack_validate` ); var listener = new Http2IllegalHpackValidationListener(); listener.finish = this.finish; @@ -900,36 +928,42 @@ Http2IllegalHpackListener.prototype.onStopRequest = function () { chan.asyncOpen(listener); }; -async function test_http2_illegalhpacksoft(serverPort) { +async function test_http2_illegalhpacksoft(serverPort, origin = "localhost") { var chan = makeHTTPChannel( - `https://localhost:${serverPort}/illegalhpacksoft` + `https://${origin}:${serverPort}/illegalhpacksoft` ); return new Promise(resolve => { var listener = new Http2IllegalHpackListener(); listener.finish = resolve; listener.serverPort = serverPort; + listener.origin = origin; listener.shouldGoAway = false; listener.shouldSucceed = false; chan.asyncOpen(listener); }); } -async function test_http2_illegalhpackhard(serverPort) { +async function test_http2_illegalhpackhard(serverPort, origin = "localhost") { var chan = makeHTTPChannel( - `https://localhost:${serverPort}/illegalhpackhard` + `https://${origin}:${serverPort}/illegalhpackhard` ); return new Promise(resolve => { var listener = new Http2IllegalHpackListener(); listener.finish = resolve; listener.serverPort = serverPort; + listener.origin = origin; listener.shouldGoAway = true; listener.shouldSucceed = false; chan.asyncOpen(listener); }); } -async function test_http2_folded_header(loadGroup, serverPort) { - var chan = makeHTTPChannel(`https://localhost:${serverPort}/foldedheader`); +async function test_http2_folded_header( + loadGroup, + serverPort, + origin = "localhost" +) { + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/foldedheader`); chan.loadGroup = loadGroup; return new Promise(resolve => { var listener = new Http2CheckListener(); @@ -939,8 +973,8 @@ async function test_http2_folded_header(loadGroup, serverPort) { }); } -async function test_http2_empty_data(serverPort) { - var chan = makeHTTPChannel(`https://localhost:${serverPort}/emptydata`); +async function test_http2_empty_data(serverPort, origin = "localhost") { + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/emptydata`); return new Promise(resolve => { var listener = new Http2CheckListener(); listener.finish = resolve; @@ -948,8 +982,8 @@ async function test_http2_empty_data(serverPort) { }); } -async function test_http2_status_phrase(serverPort) { - var chan = makeHTTPChannel(`https://localhost:${serverPort}/statusphrase`); +async function test_http2_status_phrase(serverPort, origin = "localhost") { + var chan = makeHTTPChannel(`https://${origin}:${serverPort}/statusphrase`); return new Promise(resolve => { var listener = new Http2CheckListener(); listener.finish = resolve; diff --git a/netwerk/test/unit/test_http2_with_http3_proxy.js b/netwerk/test/unit/test_http2_with_http3_proxy.js @@ -0,0 +1,344 @@ +// test HTTP/2 with a HTTP/3 prooxy + +"use strict"; + +/* import-globals-from http2_test_common.js */ + +const { Http3ProxyFilter, NodeHTTP2ProxyServer } = ChromeUtils.importESModule( + "resource://testing-common/NodeServer.sys.mjs" +); + +let concurrent_channels = []; +let loadGroup; +let serverPort; +let pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService(); +let proxyHost; +let proxyPort; +let proxyFilter; + +add_setup(async function setup() { + serverPort = Services.env.get("MOZHTTP2_PORT"); + Assert.notEqual(serverPort, null); + dump("using port " + serverPort + "\n"); + + // Set to allow the cert presented by our H2 server + do_get_profile(); + + let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( + Ci.nsIX509CertDB + ); + addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u"); + addCertFromFile(certdb, "proxy-ca.pem", "CTu,u,u"); + + Services.prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true); + Services.prefs.setBoolPref("network.http.http3.enable", true); + Services.prefs.setBoolPref("network.http.http2.enabled", true); + Services.prefs.setBoolPref("network.http.altsvc.enabled", true); + Services.prefs.setBoolPref("network.http.altsvc.oe", true); + Services.prefs.setCharPref( + "network.dns.localDomains", + "foo.example.com, alt1.example.com, bar.example.com" + ); + Services.prefs.setBoolPref( + "network.cookieJarSettings.unblocked_for_testing", + true + ); + + loadGroup = Cc["@mozilla.org/network/load-group;1"].createInstance( + Ci.nsILoadGroup + ); + + Services.prefs.setStringPref( + "services.settings.server", + `data:,#remote-settings-dummy/v1` + ); + + proxyHost = "alt1.example.com"; + proxyPort = (await create_masque_proxy_server()).masqueProxyPort; + Assert.notEqual(proxyPort, null); + Assert.notEqual(proxyPort, ""); + proxyFilter = new Http3ProxyFilter( + proxyHost, + proxyPort, + 0, + "/.well-known/masque/udp/{target_host}/{target_port}/", + "" + ); + pps.registerFilter(proxyFilter, 10); + + let h2Proxy = new NodeHTTP2ProxyServer(); + await h2Proxy.startWithoutProxyFilter(proxyPort); + Assert.equal(proxyPort, h2Proxy.port()); + + registerCleanupFunction(async () => { + Services.prefs.clearUserPref("network.http.http3.enable"); + Services.prefs.clearUserPref("network.dns.localDomains"); + Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost"); + Services.prefs.clearUserPref("network.http.altsvc.oe"); + Services.prefs.clearUserPref( + "network.http.http3.alt-svc-mapping-for-testing" + ); + await h2Proxy.stop(); + pps.unregisterFilter(proxyFilter); + }); +}); + +// hack - the header test resets the multiplex object on the server, +// so make sure header is always run before the multiplex test. +// +// make sure post_big runs first to test race condition in restarting +// a stalled stream when a SETTINGS frame arrives +add_task(async function do_test_http2_post_big() { + const { httpProxyConnectResponseCode } = await test_http2_post_big( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_basic() { + const { httpProxyConnectResponseCode } = await test_http2_basic( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_concurrent() { + const { httpProxyConnectResponseCode } = await test_http2_concurrent( + concurrent_channels, + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_concurrent_post() { + const { httpProxyConnectResponseCode } = await test_http2_concurrent_post( + concurrent_channels, + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_basic_unblocked_dep() { + const { httpProxyConnectResponseCode } = await test_http2_basic_unblocked_dep( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_doubleheader() { + const { httpProxyConnectResponseCode } = await test_http2_doubleheader( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_xhr() { + await test_http2_xhr(serverPort, "foo.example.com"); +}); + +add_task(async function do_test_http2_header() { + const { httpProxyConnectResponseCode } = await test_http2_header( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_invalid_response_header_name_spaces() { + const { httpProxyConnectResponseCode } = + await test_http2_invalid_response_header( + serverPort, + "name_spaces", + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task( + async function do_test_http2_invalid_response_header_value_line_feed() { + const { httpProxyConnectResponseCode } = + await test_http2_invalid_response_header( + serverPort, + "value_line_feed", + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); + } +); + +add_task( + async function do_test_http2_invalid_response_header_value_carriage_return() { + const { httpProxyConnectResponseCode } = + await test_http2_invalid_response_header( + serverPort, + "value_carriage_return", + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); + } +); + +add_task(async function do_test_http2_invalid_response_header_value_null() { + const { httpProxyConnectResponseCode } = + await test_http2_invalid_response_header( + serverPort, + "value_null", + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_cookie_crumbling() { + const { httpProxyConnectResponseCode } = await test_http2_cookie_crumbling( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_multiplex() { + var values = await test_http2_multiplex(serverPort, "foo.example.com"); + Assert.equal(values[0].httpProxyConnectResponseCode, 200); + Assert.equal(values[1].httpProxyConnectResponseCode, 200); + Assert.notEqual(values[0].streamID, values[1].streamID); +}); + +add_task(async function do_test_http2_big() { + const { httpProxyConnectResponseCode } = await test_http2_big( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_huge_suspended() { + const { httpProxyConnectResponseCode } = await test_http2_huge_suspended( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_post() { + const { httpProxyConnectResponseCode } = await test_http2_post( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_empty_post() { + const { httpProxyConnectResponseCode } = await test_http2_empty_post( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_patch() { + const { httpProxyConnectResponseCode } = await test_http2_patch( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_blocking_download() { + const { httpProxyConnectResponseCode } = await test_http2_blocking_download( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_illegalhpacksoft() { + const { httpProxyConnectResponseCode } = await test_http2_illegalhpacksoft( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_illegalhpackhard() { + const { httpProxyConnectResponseCode } = await test_http2_illegalhpackhard( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_folded_header() { + const { httpProxyConnectResponseCode } = await test_http2_folded_header( + loadGroup, + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_empty_data() { + const { httpProxyConnectResponseCode } = await test_http2_empty_data( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_status_phrase() { + const { httpProxyConnectResponseCode } = await test_http2_status_phrase( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_h11required_stream() { + // Add new tests above here - best to add new tests before h1 + // streams get too involved + // These next two must always come in this order + const { httpProxyConnectResponseCode } = await test_http2_h11required_stream( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_h11required_session() { + const { httpProxyConnectResponseCode } = await test_http2_h11required_session( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_retry_rst() { + const { httpProxyConnectResponseCode } = await test_http2_retry_rst( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_wrongsuite_tls13() { + const { httpProxyConnectResponseCode } = await test_http2_wrongsuite_tls13( + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); + +add_task(async function do_test_http2_continuations_over_max_response_limit() { + const { httpProxyConnectResponseCode } = + await test_http2_continuations_over_max_response_limit( + loadGroup, + serverPort, + "foo.example.com" + ); + Assert.equal(httpProxyConnectResponseCode, 200); +}); diff --git a/netwerk/test/unit/xpcshell.toml b/netwerk/test/unit/xpcshell.toml @@ -709,6 +709,16 @@ skip-if = ["os == 'android'"] run-sequentially = ["true"] # node server exceptions dont replay well head = "head_channels.js head_cache.js head_cookies.js head_trr.js head_http3.js http2_test_common.js" +["test_http2_with_http3_proxy.js"] +run-sequentially = ["true"] # node server exceptions dont replay well +head = "head_channels.js head_cache.js head_cookies.js head_trr.js head_http3.js http2_test_common.js" +skip-if = [ + "os == 'android' && os_version == '14' && processor == 'x86_64'", # Bug 1982955 + "os == 'win' && os_version == '10.2009' && processor == 'x86_64'", # Bug 1807931 + "os == 'win' && os_version == '11.26100' && processor == 'x86'", # Bug 1807931 + "os == 'win' && os_version == '11.26100' && processor == 'x86_64' && msix", # Bug 1807931 +] + ["test_http3.js"] head = "head_cookies.js head_channels.js head_cache.js head_http3.js http3_common.js" run-sequentially = ["true"] # http3server