commit c7967e41ed424b40194f5bbb739b7f59eb71c454
parent 175e66322f3fda0cd205102880e3f70e10f63eec
Author: Atila Butkovits <abutkovits@mozilla.com>
Date: Mon, 13 Oct 2025 21:16:04 +0300
Revert "Bug 1993438 - Run tests in http3_common.js with HTTP/3 proxy, r=necko-reviewers,valentin,jesup" for causing failures at test_http3_with_proxy.js.
This reverts commit da45a0fbf96029cc1067c9546f5c136b8a721e1e.
Revert "Bug 1993438 - Make Alt-Svc work for connect-udp, r=necko-reviewers,valentin"
This reverts commit ba8f1b8791ed8233117d4b4b63ab2aabd93aa59b.
Revert "Bug 1993438 - Modernize test_http3.js and extract tests into a separate file, r=necko-reviewers,valentin"
This reverts commit d037b11c9b5a45658b1c9337eebf823fa64b2d83.
Diffstat:
6 files changed, 550 insertions(+), 1015 deletions(-)
diff --git a/netwerk/protocol/http/AlternateServices.cpp b/netwerk/protocol/http/AlternateServices.cpp
@@ -1130,8 +1130,8 @@ void AltSvcCache::UpdateAltServiceMapping(
}
if (map->IsHttp3()) {
- bool isProxyAllowed = pi ? (pi->IsDirect() || pi->IsHttp3Proxy()) : true;
- if (!isProxyAllowed) {
+ bool isDirectOrNoProxy = pi ? pi->IsDirect() : true;
+ if (!isDirectOrNoProxy) {
LOG(
("AltSvcCache::UpdateAltServiceMapping %p map %p ignored h3 because "
"proxy is in use %p\n",
diff --git a/netwerk/protocol/http/Http3ConnectUDPStream.cpp b/netwerk/protocol/http/Http3ConnectUDPStream.cpp
@@ -101,19 +101,13 @@ nsresult Http3ConnectUDPStream::TryActivating() {
return NS_ERROR_UNEXPECTED;
}
- bool useRoutedHost =
- !mTransaction->ConnectionInfo()->GetRoutedHost().IsEmpty();
- nsresult rv = builder->Set(
- "target_host"_ns, useRoutedHost
- ? mTransaction->ConnectionInfo()->GetRoutedHost()
- : mTransaction->ConnectionInfo()->GetOrigin());
+ nsresult rv = builder->Set("target_host"_ns,
+ mTransaction->ConnectionInfo()->GetOrigin());
if (NS_FAILED(rv)) {
return rv;
}
rv = builder->Set("target_port"_ns,
- useRoutedHost
- ? mTransaction->ConnectionInfo()->RoutedPort()
- : mTransaction->ConnectionInfo()->OriginPort());
+ mTransaction->ConnectionInfo()->OriginPort());
if (NS_FAILED(rv)) {
return rv;
}
diff --git a/netwerk/test/unit/http3_common.js b/netwerk/test/unit/http3_common.js
@@ -1,719 +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";
-
-/* import-globals-from head_cache.js */
-/* import-globals-from head_cookies.js */
-/* import-globals-from head_channels.js */
-/* import-globals-from head_http3.js */
-
-const { HttpServer } = ChromeUtils.importESModule(
- "resource://testing-common/httpd.sys.mjs"
-);
-
-function makeChan(uri) {
- let chan = NetUtil.newChannel({
- uri,
- loadUsingSystemPrincipal: true,
- }).QueryInterface(Ci.nsIHttpChannel);
- chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
- return chan;
-}
-
-// Promise-backed Http3CheckListener
-class Http3CheckListener {
- constructor(
- { expectedStatus = Cr.NS_OK, expectedRoute = "" } = {},
- resolve,
- reject
- ) {
- this.onDataAvailableFired = false;
- this.expectedStatus = expectedStatus;
- this.expectedRoute = expectedRoute;
- this._resolve = resolve;
- this._reject = reject;
- }
-
- onStartRequest(request) {
- Assert.ok(request instanceof Ci.nsIHttpChannel);
- Assert.equal(request.status, this.expectedStatus);
- if (Components.isSuccessCode(this.expectedStatus)) {
- Assert.equal(request.responseStatus, 200);
- }
- }
-
- onDataAvailable(request, stream, off, cnt) {
- this.onDataAvailableFired = true;
- read_stream(stream, cnt);
- }
-
- onStopRequest(request, status) {
- Assert.equal(status, this.expectedStatus);
-
- let routed = "NA";
- try {
- routed = request.getRequestHeader("Alt-Used");
- } catch (e) {}
- dump("routed is " + routed + "\n");
-
- Assert.equal(routed, this.expectedRoute);
-
- if (Components.isSuccessCode(this.expectedStatus)) {
- let httpVersion = "";
- try {
- httpVersion = request.protocolVersion;
- } catch (e) {}
- Assert.equal(httpVersion, "h3");
- Assert.equal(this.onDataAvailableFired, true);
- Assert.equal(request.getResponseHeader("X-Firefox-Http3"), "h3");
- }
-
- this._resolve?.(request);
- }
-}
-
-class WaitForHttp3Listener extends Http3CheckListener {
- constructor(
- {
- expectedStatus = Cr.NS_OK,
- expectedRoute = "",
- uri = "",
- h3AltSvc = "",
- retry,
- delayMs = 500,
- } = {},
- resolve,
- reject
- ) {
- super({ expectedStatus, expectedRoute }, resolve, reject);
- this.uri = uri;
- this.h3AltSvc = h3AltSvc;
- this._retry = retry; // function to re-open the request
- this._delayMs = delayMs; // poll interval
- }
-
- onStopRequest(request, status) {
- Assert.equal(status, this.expectedStatus);
-
- let routed = "NA";
- try {
- routed = request.getRequestHeader("Alt-Used");
- } catch (e) {}
- dump(`routed is ${routed}\n`);
-
- let httpVersion = "";
- try {
- httpVersion = request.protocolVersion;
- } catch (e) {}
-
- if (routed === this.expectedRoute) {
- // (This is where run_next_test() used to be.)
- Assert.equal(routed, this.expectedRoute); // useful log/assert
- Assert.equal(httpVersion, "h3");
- this._resolve?.(request);
- return;
- }
-
- // Not routed yet: mirror old behavior (log + supportsHTTP3 check + retry)
- dump("poll later for alt-svc mapping\n");
- if (httpVersion === "h2") {
- request.QueryInterface(Ci.nsIHttpChannelInternal);
- Assert.ok(request.supportsHTTP3);
- }
-
- if (typeof this._retry === "function") {
- // schedule another attempt (replaces do_test_pending/do_timeout recursion)
- do_timeout(this._delayMs, () =>
- this._retry(this.uri, this.expectedRoute, this.h3AltSvc)
- );
- }
- // Promise remains pending until a later attempt matches expectedRoute.
- }
-}
-
-// Factory to create { listener, promise }
-function createHttp3CheckListener(options = {}) {
- let resolve, reject;
- const promise = new Promise((res, rej) => {
- resolve = res;
- reject = rej;
- });
- const listener = new Http3CheckListener(options, resolve, reject);
- return { listener, promise };
-}
-
-function createWaitForHttp3Listener(options = {}) {
- let resolve, reject;
- const promise = new Promise((res, rej) => {
- resolve = res;
- reject = rej;
- });
- const listener = new WaitForHttp3Listener(options, resolve, reject);
- return { listener, promise };
-}
-
-// --- Async wrapper that does the polling by re-issuing the request ---
-async function waitForHttp3Route(
- uri,
- expectedRoute,
- altSvc,
- { delayMs = 500 } = {}
-) {
- let listenerRef;
-
- // Function to (re)open the channel using the same listener instance.
- const retry = () => {
- const chan = makeChan(uri);
- if (altSvc) {
- chan.setRequestHeader("x-altsvc", altSvc, false);
- }
- chan.asyncOpen(listenerRef);
- };
-
- const { listener, promise } = createWaitForHttp3Listener({
- expectedStatus: Cr.NS_OK,
- expectedRoute,
- uri,
- h3AltSvc: altSvc,
- retry,
- delayMs,
- });
- listenerRef = listener;
-
- // Kick off first attempt; subsequent attempts are scheduled by the listener.
- retry();
-
- // Resolves only when routed === expectedRoute
- return promise;
-}
-
-// Promise-backed MultipleListener
-class MultipleListener {
- constructor(
- {
- number_of_parallel_requests = 0,
- expectedRoute = "",
- with_error = Cr.NS_OK, // NS_OK means we expect success for all
- } = {},
- resolve,
- reject
- ) {
- this.number_of_parallel_requests = number_of_parallel_requests;
- this.expectedRoute = expectedRoute;
- this.with_error = with_error;
-
- this.count_of_done_requests = 0;
- this.error_found_onstart = false;
- this.error_found_onstop = false;
- this.need_cancel_found = false;
-
- this._resolve = resolve;
- this._reject = reject;
- }
-
- onStartRequest(request) {
- Assert.ok(request instanceof Ci.nsIHttpChannel);
-
- // Optional cancel behavior via header "CancelMe"
- let need_cancel = "";
- try {
- need_cancel = request.getRequestHeader("CancelMe");
- } catch (_) {}
- if (need_cancel !== "") {
- this.need_cancel_found = true;
- request.cancel(Cr.NS_ERROR_ABORT);
- return;
- }
-
- // Original logic: either 200 OK for success, or exactly one failure
- if (Components.isSuccessCode(request.status)) {
- Assert.equal(request.responseStatus, 200);
- } else if (this.error_found_onstart) {
- // Fail fast: more than one failing request on start
- this._reject?.(
- new Error("We should have only one request failing (onStart).")
- );
- } else {
- Assert.equal(request.status, this.with_error);
- this.error_found_onstart = true;
- }
- }
-
- onDataAvailable(request, stream, off, cnt) {
- read_stream(stream, cnt);
- }
-
- onStopRequest(request) {
- // Check Alt-Used routing matches expectation
- let routed = "";
- try {
- routed = request.getRequestHeader("Alt-Used");
- } catch (_) {}
- Assert.equal(routed, this.expectedRoute);
-
- // If success, ensure HTTP/3
- if (Components.isSuccessCode(request.status)) {
- let httpVersion = "";
- try {
- httpVersion = request.protocolVersion;
- } catch (_) {}
- Assert.equal(httpVersion, "h3");
- }
-
- // Track/validate failures (at most one)
- if (!Components.isSuccessCode(request.status)) {
- if (this.error_found_onstop) {
- this._reject?.(
- new Error("We should have only one request failing (onStop).")
- );
- return;
- }
- Assert.equal(request.status, this.with_error);
- this.error_found_onstop = true;
- }
-
- // Count completion and maybe resolve
- this.count_of_done_requests++;
- if (this.count_of_done_requests === this.number_of_parallel_requests) {
- if (Components.isSuccessCode(this.with_error)) {
- // All were expected to succeed
- Assert.equal(this.error_found_onstart, false);
- Assert.equal(this.error_found_onstop, false);
- } else {
- // One failure was expected OR a cancel path was exercised
- Assert.ok(this.error_found_onstart || this.need_cancel_found);
- Assert.equal(this.error_found_onstop, true);
- }
- this._resolve?.();
- }
- }
-}
-
-// Factory to create { listener, promise }
-function createMultipleListener(options = {}) {
- let resolve, reject;
- const promise = new Promise((res, rej) => {
- resolve = res;
- reject = rej;
- });
- const listener = new MultipleListener(options, resolve, reject);
- return { listener, promise };
-}
-
-async function do_test_multiple_requests(
- number_of_parallel_requests,
- h3Route,
- httpsOrigin
-) {
- dump("test_multiple_requests()\n");
-
- const { listener, promise } = createMultipleListener({
- number_of_parallel_requests,
- expectedRoute: h3Route,
- with_error: Cr.NS_OK,
- });
-
- for (let i = 0; i < number_of_parallel_requests; i++) {
- const chan = makeChan(httpsOrigin + "20000");
- chan.asyncOpen(listener);
- }
-
- await promise;
-}
-
-async function do_test_request_cancelled_by_server(h3Route, httpsOrigin) {
- dump("do_test_request_cancelled_by_server()\n");
-
- const { listener, promise } = createHttp3CheckListener({
- expectedStatus: Cr.NS_ERROR_NET_INTERRUPT,
- expectedRoute: h3Route,
- });
-
- const chan = makeChan(httpsOrigin + "RequestCancelled");
- chan.asyncOpen(listener);
-
- // Resolves at the point where run_next_test() used to be called
- await promise;
-}
-
-// Promise-backed Http3CheckListener must already exist:
-// createHttp3CheckListener({ expectedStatus, expectedRoute })
-
-class CancelRequestListener extends Http3CheckListener {
- constructor({ expectedRoute = "" } = {}, resolve, reject) {
- super(
- { expectedStatus: Cr.NS_ERROR_ABORT, expectedRoute },
- resolve,
- reject
- );
- }
-
- onStartRequest(request) {
- Assert.ok(request instanceof Ci.nsIHttpChannel);
- Assert.equal(Components.isSuccessCode(request.status), true);
- // Cancel the request immediately (simulate Necko cancelling)
- request.cancel(Cr.NS_ERROR_ABORT);
- }
-}
-
-function createCancelRequestListener(options = {}) {
- let resolve, reject;
- const promise = new Promise((res, rej) => {
- resolve = res;
- reject = rej;
- });
- const listener = new CancelRequestListener(options, resolve, reject);
- return { listener, promise };
-}
-
-// Cancel stream after OnStartRequest.
-async function do_test_stream_cancelled_by_necko(h3Route, httpsOrigin) {
- dump("do_test_stream_cancelled_by_necko()\n");
-
- const { listener, promise } = createCancelRequestListener({
- expectedRoute: h3Route,
- });
-
- const chan = makeChan(httpsOrigin + "20000");
- chan.asyncOpen(listener);
-
- // Resolves at the end of onStopRequest (where run_next_test() used to be)
- await promise;
-}
-
-async function do_test_multiple_request_one_is_cancelled(
- number_of_parallel_requests,
- h3Route,
- httpsOrigin
-) {
- dump("do_test_multiple_request_one_is_cancelled()\n");
-
- const { listener, promise } = createMultipleListener({
- number_of_parallel_requests,
- expectedRoute: h3Route,
- with_error: Cr.NS_ERROR_NET_INTERRUPT, // one request is expected to fail (server-cancelled)
- });
-
- for (let i = 0; i < number_of_parallel_requests; i++) {
- let uri = httpsOrigin + "20000";
- if (i === 4) {
- // Add a request that will be cancelled by the server.
- uri = httpsOrigin + "RequestCancelled";
- }
- const chan = makeChan(uri);
- chan.asyncOpen(listener);
- }
-
- // Resolves when all parallel requests complete and invariants are checked
- await promise;
-}
-
-async function do_test_multiple_request_one_is_cancelled_by_necko(
- number_of_parallel_requests,
- h3Route,
- httpsOrigin
-) {
- dump("do_test_multiple_request_one_is_cancelled_by_necko()\n");
-
- const { listener, promise } = createMultipleListener({
- number_of_parallel_requests,
- expectedRoute: h3Route,
- with_error: Cr.NS_ERROR_ABORT,
- });
-
- for (let i = 0; i < number_of_parallel_requests; i++) {
- let chan = makeChan(httpsOrigin + "20000");
- if (i === 4) {
- // MultipleListener will cancel request with this header.
- chan.setRequestHeader("CancelMe", "true", false);
- }
- chan.asyncOpen(listener);
- }
-
- // Resolves when all parallel requests complete and invariants are checked
- await promise;
-}
-
-// Promise-backed Http3CheckListener assumed available:
-// function createHttp3CheckListener({ expectedStatus, expectedRoute })
-
-class PostListener extends Http3CheckListener {
- constructor(opts = {}, resolve, reject) {
- super(opts, resolve, reject);
- }
- onDataAvailable(request, stream, off, cnt) {
- this.onDataAvailableFired = true;
- read_stream(stream, cnt);
- }
-}
-
-// Factory for PostListener
-function createPostListener(options = {}) {
- let resolve, reject;
- const promise = new Promise((res, rej) => {
- resolve = res;
- reject = rej;
- });
- const listener = new PostListener(options, resolve, reject);
- return { listener, promise };
-}
-
-// Helper to perform a POST (or any method with a body)
-function openWithBody(
- content,
- chan,
- method = "POST",
- contentType = "text/plain"
-) {
- const stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
- Ci.nsIStringInputStream
- );
- stream.setByteStringData(content);
-
- const uchan = chan.QueryInterface(Ci.nsIUploadChannel);
- uchan.setUploadStream(stream, contentType, stream.available());
- chan.requestMethod = method;
- return chan;
-}
-
-// Generate a post with known pre-calculated md5 sum.
-function generateContent(size) {
- let content = "";
- for (let i = 0; i < size; i++) {
- content += "0";
- }
- return content;
-}
-
-let post = generateContent(10);
-
-// Test a simple POST (async)
-async function do_test_post(httpsOrigin, h3Route) {
- dump("do_test_post()\n");
-
- const chan = makeChan(httpsOrigin + "post");
- openWithBody(post, chan, "POST");
-
- const { listener, promise } = createPostListener({
- expectedStatus: Cr.NS_OK,
- expectedRoute: h3Route,
- });
-
- chan.asyncOpen(listener);
- await promise; // resolves at end of onStopRequest in Http3CheckListener
-}
-
-// Test a simple PATCH
-async function do_test_patch(httpsOrigin, h3Route) {
- dump("do_test_post()\n");
-
- const chan = makeChan(httpsOrigin + "patch");
- openWithBody(post, chan, "PATCH");
-
- const { listener, promise } = createPostListener({
- expectedStatus: Cr.NS_OK,
- expectedRoute: h3Route,
- });
-
- chan.asyncOpen(listener);
- await promise;
-}
-
-let h1Server = null;
-let altsvcHost = "";
-let httpOrigin = "";
-
-function h1Response(metadata, response) {
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- response.setHeader("Content-Type", "text/plain", false);
- response.setHeader("Connection", "close", false);
- response.setHeader("Cache-Control", "no-cache", false);
- response.setHeader("Access-Control-Allow-Origin", "*", false);
- response.setHeader("Access-Control-Allow-Method", "GET", false);
- response.setHeader("Access-Control-Allow-Headers", "x-altsvc", false);
-
- try {
- let hval = "h3=" + metadata.getHeader("x-altsvc");
- response.setHeader("Alt-Svc", hval, false);
- } catch (e) {}
-
- let body = "Q: What did 0 say to 8? A: Nice Belt!\n";
- response.bodyOutputStream.write(body, body.length);
-}
-
-function h1ServerWK(metadata, response) {
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- response.setHeader("Content-Type", "application/json", false);
- response.setHeader("Connection", "close", false);
- response.setHeader("Cache-Control", "no-cache", false);
- response.setHeader("Access-Control-Allow-Origin", "*", false);
- response.setHeader("Access-Control-Allow-Method", "GET", false);
- response.setHeader("Access-Control-Allow-Headers", "x-altsvc", false);
-
- let body = `["http://${altsvcHost}:${h1Server.identity.primaryPort}"]`;
- response.bodyOutputStream.write(body, body.length);
-}
-
-function setup_h1_server(host) {
- altsvcHost = host;
- h1Server = new HttpServer();
- h1Server.registerPathHandler("/http3-test", h1Response);
- h1Server.registerPathHandler("/.well-known/http-opportunistic", h1ServerWK);
- h1Server.registerPathHandler("/VersionFallback", h1Response);
- h1Server.start(-1);
- h1Server.identity.setPrimary(
- "http",
- altsvcHost,
- h1Server.identity.primaryPort
- );
- httpOrigin = `http://${altsvcHost}:${h1Server.identity.primaryPort}/`;
- registerCleanupFunction(() => {
- h1Server.stop();
- });
-}
-
-// Promise-backed base assumed available:
-// class Http3CheckListener { ... }
-// function createHttp3CheckListener(opts) { return { listener, promise }; }
-
-class SlowReceiverListener extends Http3CheckListener {
- constructor(
- {
- expectedStatus = Cr.NS_OK,
- expectedRoute = "",
- expectedBytes = 10_000_000,
- } = {},
- resolve,
- reject
- ) {
- super({ expectedStatus, expectedRoute }, resolve, reject);
- this.count = 0;
- this.expectedBytes = expectedBytes;
- }
-
- onDataAvailable(request, stream, off, cnt) {
- this.onDataAvailableFired = true;
- this.count += cnt;
- read_stream(stream, cnt);
- }
-
- onStopRequest(request, status) {
- Assert.equal(status, this.expectedStatus);
- Assert.equal(this.count, this.expectedBytes);
-
- let routed = "NA";
- try {
- routed = request.getRequestHeader("Alt-Used");
- } catch (e) {}
- dump(`routed is ${routed}\n`);
- Assert.equal(routed, this.expectedRoute);
-
- if (Components.isSuccessCode(this.expectedStatus)) {
- let httpVersion = "";
- try {
- httpVersion = request.protocolVersion;
- } catch (e) {}
- Assert.equal(httpVersion, "h3");
- Assert.equal(this.onDataAvailableFired, true);
- }
-
- // Resolve where run_next_test() used to be
- this._resolve?.(request);
- }
-}
-
-function createSlowReceiverListener(options = {}) {
- let resolve, reject;
- const promise = new Promise((res, rej) => {
- resolve = res;
- reject = rej;
- });
- const listener = new SlowReceiverListener(options, resolve, reject);
- return { listener, promise };
-}
-
-// Test: slow receiver (suspend, then resume)
-async function do_test_slow_receiver(httpsOrigin, h3Route) {
- dump("do_test_slow_receiver()\n");
-
- const chan = makeChan(httpsOrigin + "10000000");
-
- const { listener, promise } = createSlowReceiverListener({
- expectedStatus: Cr.NS_OK,
- expectedRoute: h3Route,
- expectedBytes: 10_000_000,
- });
-
- chan.asyncOpen(listener);
-
- // Suspend immediately, then resume after 1s (replaces do_test_pending/do_timeout)
- chan.suspend();
- await new Promise(r => do_timeout(1000, r));
- chan.resume();
-
- // Wait for completion (used to be run_next_test/do_test_finished)
- await promise;
-}
-
-// Promise-backed listener for version fallback checks
-class CheckFallbackListener {
- constructor(resolve, reject) {
- this._resolve = resolve;
- this._reject = reject;
- }
-
- onStartRequest(request) {
- Assert.ok(request instanceof Ci.nsIHttpChannel);
- Assert.equal(request.status, Cr.NS_OK);
- Assert.equal(request.responseStatus, 200);
- }
-
- onDataAvailable(request, stream, off, cnt) {
- read_stream(stream, cnt);
- }
-
- onStopRequest(request, status) {
- Assert.equal(status, Cr.NS_OK);
-
- let routed = "NA";
- try {
- routed = request.getRequestHeader("Alt-Used");
- } catch (e) {}
- dump(`routed is ${routed}\n`);
- Assert.equal(routed, "0");
-
- let httpVersion = "";
- try {
- httpVersion = request.protocolVersion;
- } catch (e) {}
- Assert.equal(httpVersion, "http/1.1");
-
- // Resolve where run_next_test() used to be called
- this._resolve?.(request);
- }
-}
-
-// Factory to create { listener, promise }
-function createCheckFallbackListener() {
- let resolve, reject;
- const promise = new Promise((res, rej) => {
- resolve = res;
- reject = rej;
- });
- const listener = new CheckFallbackListener(resolve, reject);
- return { listener, promise };
-}
-
-// Server cancels request with VersionFallback.
-async function do_test_version_fallback(httpsOrigin) {
- dump("do_test_version_fallback()\n");
-
- const chan = makeChan(httpsOrigin + "VersionFallback");
- const { listener, promise } = createCheckFallbackListener();
-
- chan.asyncOpen(listener);
-
- await promise;
-}
diff --git a/netwerk/test/unit/test_http3.js b/netwerk/test/unit/test_http3.js
@@ -1,18 +1,64 @@
"use strict";
-/* import-globals-from http3_common.js */
+const { HttpServer } = ChromeUtils.importESModule(
+ "resource://testing-common/httpd.sys.mjs"
+);
+
+// Generate a post with known pre-calculated md5 sum.
+function generateContent(size) {
+ let content = "";
+ for (let i = 0; i < size; i++) {
+ content += "0";
+ }
+ return content;
+}
+
+let post = generateContent(10);
// Max concurent stream number in neqo is 100.
// Openning 120 streams will test queuing of streams.
let number_of_parallel_requests = 120;
+let h1Server = null;
let h3Route;
let httpsOrigin;
+let httpOrigin;
let h3AltSvc;
let h3Port;
-let h3ServerDomain;
+
let prefs;
-add_setup(async function () {
+let tests = [
+ // This test must be the first because it setsup alt-svc connection, that
+ // other tests use.
+ test_https_alt_svc,
+ test_multiple_requests,
+ test_request_cancelled_by_server,
+ test_stream_cancelled_by_necko,
+ test_multiple_request_one_is_cancelled,
+ test_multiple_request_one_is_cancelled_by_necko,
+ test_post,
+ test_patch,
+ test_http_alt_svc,
+ test_slow_receiver,
+ // This test should be at the end, because it will close http3
+ // connection and the transaction will switch to already existing http2
+ // connection.
+ // TODO: Bug 1582667 should try to fix issue with connection being closed.
+ test_version_fallback,
+ testsDone,
+];
+
+let current_test = 0;
+
+function run_next_test() {
+ if (current_test < tests.length) {
+ dump("starting test number " + current_test + "\n");
+ tests[current_test]();
+ current_test++;
+ }
+}
+
+function run_test() {
let h2Port = Services.env.get("MOZHTTP2_PORT");
Assert.notEqual(h2Port, null);
Assert.notEqual(h2Port, "");
@@ -20,21 +66,185 @@ add_setup(async function () {
Assert.notEqual(h3Port, null);
Assert.notEqual(h3Port, "");
h3AltSvc = ":" + h3Port;
- h3ServerDomain = "foo.example.com";
- h3Route = `${h3ServerDomain}:${h3Port}`;
+
+ h3Route = "foo.example.com:" + h3Port;
do_get_profile();
prefs = Services.prefs;
prefs.setBoolPref("network.http.http3.enable", true);
- prefs.setCharPref(
- "network.dns.localDomains",
- "foo.example.com, alt1.example.com"
- );
+ prefs.setCharPref("network.dns.localDomains", "foo.example.com");
// We always resolve elements of localDomains as it's hardcoded without the
// following pref:
prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true);
prefs.setBoolPref("network.http.altsvc.oe", true);
+ // The certificate for the http3server server is for foo.example.com and
+ // is signed by http2-ca.pem so add that cert to the trust list as a
+ // signing cert.
+ let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
+ Ci.nsIX509CertDB
+ );
+ addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
+ httpsOrigin = "https://foo.example.com:" + h2Port + "/";
+
+ h1Server = new HttpServer();
+ h1Server.registerPathHandler("/http3-test", h1Response);
+ h1Server.registerPathHandler("/.well-known/http-opportunistic", h1ServerWK);
+ h1Server.registerPathHandler("/VersionFallback", h1Response);
+ h1Server.start(-1);
+ h1Server.identity.setPrimary(
+ "http",
+ "foo.example.com",
+ h1Server.identity.primaryPort
+ );
+ httpOrigin = "http://foo.example.com:" + h1Server.identity.primaryPort + "/";
+
+ run_next_test();
+}
+
+function h1Response(metadata, response) {
+ response.setStatusLine(metadata.httpVersion, 200, "OK");
+ response.setHeader("Content-Type", "text/plain", false);
+ response.setHeader("Connection", "close", false);
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Access-Control-Allow-Origin", "*", false);
+ response.setHeader("Access-Control-Allow-Method", "GET", false);
+ response.setHeader("Access-Control-Allow-Headers", "x-altsvc", false);
+
+ try {
+ let hval = "h3=" + metadata.getHeader("x-altsvc");
+ response.setHeader("Alt-Svc", hval, false);
+ } catch (e) {}
+
+ let body = "Q: What did 0 say to 8? A: Nice Belt!\n";
+ response.bodyOutputStream.write(body, body.length);
+}
+
+function h1ServerWK(metadata, response) {
+ response.setStatusLine(metadata.httpVersion, 200, "OK");
+ response.setHeader("Content-Type", "application/json", false);
+ response.setHeader("Connection", "close", false);
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Access-Control-Allow-Origin", "*", false);
+ response.setHeader("Access-Control-Allow-Method", "GET", false);
+ response.setHeader("Access-Control-Allow-Headers", "x-altsvc", false);
+
+ let body = '["http://foo.example.com:' + h1Server.identity.primaryPort + '"]';
+ response.bodyOutputStream.write(body, body.length);
+}
+
+function makeChan(uri) {
+ let chan = NetUtil.newChannel({
+ uri,
+ loadUsingSystemPrincipal: true,
+ }).QueryInterface(Ci.nsIHttpChannel);
+ chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
+ return chan;
+}
+
+let Http3CheckListener = function () {};
+
+Http3CheckListener.prototype = {
+ onDataAvailableFired: false,
+ expectedStatus: Cr.NS_OK,
+ expectedRoute: "",
+
+ onStartRequest: function testOnStartRequest(request) {
+ Assert.ok(request instanceof Ci.nsIHttpChannel);
+
+ Assert.equal(request.status, this.expectedStatus);
+ if (Components.isSuccessCode(this.expectedStatus)) {
+ Assert.equal(request.responseStatus, 200);
+ }
+ },
+
+ onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) {
+ this.onDataAvailableFired = true;
+ read_stream(stream, cnt);
+ },
+
+ onStopRequest: function testOnStopRequest(request, status) {
+ Assert.equal(status, this.expectedStatus);
+ let routed = "NA";
+ try {
+ routed = request.getRequestHeader("Alt-Used");
+ } catch (e) {}
+ dump("routed is " + routed + "\n");
+
+ Assert.equal(routed, this.expectedRoute);
+
+ if (Components.isSuccessCode(this.expectedStatus)) {
+ let httpVersion = "";
+ try {
+ httpVersion = request.protocolVersion;
+ } catch (e) {}
+ Assert.equal(httpVersion, "h3");
+ Assert.equal(this.onDataAvailableFired, true);
+ Assert.equal(request.getResponseHeader("X-Firefox-Http3"), "h3");
+ }
+ run_next_test();
+ do_test_finished();
+ },
+};
+
+let WaitForHttp3Listener = function () {};
+
+WaitForHttp3Listener.prototype = new Http3CheckListener();
+
+WaitForHttp3Listener.prototype.uri = "";
+WaitForHttp3Listener.prototype.h3AltSvc = "";
+
+WaitForHttp3Listener.prototype.onStopRequest = function testOnStopRequest(
+ request,
+ status
+) {
+ Assert.equal(status, this.expectedStatus);
+
+ let routed = "NA";
+ try {
+ routed = request.getRequestHeader("Alt-Used");
+ } catch (e) {}
+ dump("routed is " + routed + "\n");
+
+ let httpVersion = "";
+ try {
+ httpVersion = request.protocolVersion;
+ } catch (e) {}
+
+ if (routed == this.expectedRoute) {
+ Assert.equal(routed, this.expectedRoute); // always true, but a useful log
+ Assert.equal(httpVersion, "h3");
+ run_next_test();
+ } else {
+ dump("poll later for alt svc mapping\n");
+ if (httpVersion == "h2") {
+ request.QueryInterface(Ci.nsIHttpChannelInternal);
+ Assert.ok(request.supportsHTTP3);
+ }
+ do_test_pending();
+ do_timeout(500, () => {
+ doTest(this.uri, this.expectedRoute, this.h3AltSvc);
+ });
+ }
+
+ do_test_finished();
+};
+
+function doTest(uri, expectedRoute, altSvc) {
+ let chan = makeChan(uri);
+ let listener = new WaitForHttp3Listener();
+ listener.uri = uri;
+ listener.expectedRoute = expectedRoute;
+ listener.h3AltSvc = altSvc;
+ chan.setRequestHeader("x-altsvc", altSvc, false);
+ chan.asyncOpen(listener);
+}
+
+// Test Alt-Svc for http3.
+// H2 server returns alt-svc=h3=:h3port
+function test_https_alt_svc() {
+ dump("test_https_alt_svc()\n");
+ do_test_pending();
if (mozinfo.os == "android") {
// Set necessary prefs to make Firefox connect to the http3Server on the
// host machine.
@@ -42,99 +252,341 @@ add_setup(async function () {
const overrideService = Cc[
"@mozilla.org/network/native-dns-override;1"
].getService(Ci.nsINativeDNSResolverOverride);
- overrideService.addIPOverride(h3ServerDomain, "10.0.2.2");
+ overrideService.addIPOverride("foo.example.com", "10.0.2.2");
prefs.setCharPref(
"network.http.http3.alt-svc-mapping-for-testing",
- `${h3ServerDomain};h3=:${h3Port}`
+ `foo.example.com;h3=:${h3Port}`
);
}
+ doTest(httpsOrigin + "http3-test", h3Route, h3AltSvc);
+}
- // The certificate for the http3server server is for foo.example.com and
- // is signed by http2-ca.pem so add that cert to the trust list as a
- // signing cert.
- let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
- Ci.nsIX509CertDB
- );
- addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
- httpsOrigin = `https://${h3ServerDomain}:${h2Port}/`;
-
- registerCleanupFunction(() => {
- prefs.clearUserPref("network.http.http3.enable");
- prefs.clearUserPref("network.dns.localDomains");
- prefs.clearUserPref("network.proxy.allow_hijacking_localhost");
- prefs.clearUserPref("network.http.altsvc.oe");
- });
-});
-
-add_task(async function test_https_alt_svc() {
- await waitForHttp3Route(httpsOrigin + "http3-test", h3Route, h3AltSvc, {
- delayMs: 500,
- });
-});
-
-add_task(async function test_multiple_requests() {
- await do_test_multiple_requests(
- number_of_parallel_requests,
- h3Route,
- httpsOrigin
- );
-});
+// Listener for a number of parallel requests. if with_error is set, one of
+// the channels will be cancelled (by the server or in onStartRequest).
+let MultipleListener = function () {};
-add_task(async function test_request_cancelled_by_server() {
- await do_test_request_cancelled_by_server(h3Route, httpsOrigin);
-});
+MultipleListener.prototype = {
+ number_of_parallel_requests: 0,
+ with_error: Cr.NS_OK,
+ count_of_done_requests: 0,
+ error_found_onstart: false,
+ error_found_onstop: false,
+ need_cancel_found: false,
-add_task(async function test_stream_cancelled_by_necko() {
- await do_test_stream_cancelled_by_necko(h3Route, httpsOrigin);
-});
+ onStartRequest: function testOnStartRequest(request) {
+ Assert.ok(request instanceof Ci.nsIHttpChannel);
-add_task(async function test_multiple_request_one_is_cancelled() {
- await do_test_multiple_request_one_is_cancelled(
- number_of_parallel_requests,
- h3Route,
- httpsOrigin
- );
-});
+ let need_cancel = "";
+ try {
+ need_cancel = request.getRequestHeader("CancelMe");
+ } catch (e) {}
+ if (need_cancel != "") {
+ this.need_cancel_found = true;
+ request.cancel(Cr.NS_ERROR_ABORT);
+ } else if (Components.isSuccessCode(request.status)) {
+ Assert.equal(request.responseStatus, 200);
+ } else if (this.error_found_onstart) {
+ do_throw("We should have only one request failing.");
+ } else {
+ Assert.equal(request.status, this.with_error);
+ this.error_found_onstart = true;
+ }
+ },
-add_task(async function test_multiple_request_one_is_cancelled_by_necko() {
- await do_test_multiple_request_one_is_cancelled_by_necko(
- number_of_parallel_requests,
- h3Route,
- httpsOrigin
- );
-});
-
-add_task(async function test_post() {
- await do_test_post(httpsOrigin, h3Route);
-});
-
-add_task(async function test_patch() {
- await do_test_patch(httpsOrigin, h3Route);
-});
-
-add_task(
- {
- // Skip this test on Android because the httpOrigin (http://foo.example.com)
- // is on 127.0.0.1, while the http3Server (https://foo.example.com) is
- // on 10.0.2.2. Currently, we can't change the IP mapping dynamically.
- skip_if: () => mozinfo.os == "android",
+ onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) {
+ read_stream(stream, cnt);
},
- async function test_http_alt_svc() {
- setup_h1_server(h3ServerDomain);
- await waitForHttp3Route(httpOrigin + "http3-test", h3Route, h3AltSvc, {
- delayMs: 500,
- });
+
+ onStopRequest: function testOnStopRequest(request) {
+ let routed = "";
+ try {
+ routed = request.getRequestHeader("Alt-Used");
+ } catch (e) {}
+ Assert.equal(routed, this.expectedRoute);
+
+ if (Components.isSuccessCode(request.status)) {
+ let httpVersion = "";
+ try {
+ httpVersion = request.protocolVersion;
+ } catch (e) {}
+ Assert.equal(httpVersion, "h3");
+ }
+
+ if (!Components.isSuccessCode(request.status)) {
+ if (this.error_found_onstop) {
+ do_throw("We should have only one request failing.");
+ } else {
+ Assert.equal(request.status, this.with_error);
+ this.error_found_onstop = true;
+ }
+ }
+ this.count_of_done_requests++;
+ if (this.count_of_done_requests == this.number_of_parallel_requests) {
+ if (Components.isSuccessCode(this.with_error)) {
+ Assert.equal(this.error_found_onstart, false);
+ Assert.equal(this.error_found_onstop, false);
+ } else {
+ Assert.ok(this.error_found_onstart || this.need_cancel_found);
+ Assert.equal(this.error_found_onstop, true);
+ }
+ run_next_test();
+ }
+ do_test_finished();
+ },
+};
+
+// Multiple requests
+function test_multiple_requests() {
+ dump("test_multiple_requests()\n");
+
+ let listener = new MultipleListener();
+ listener.number_of_parallel_requests = number_of_parallel_requests;
+ listener.expectedRoute = h3Route;
+
+ for (let i = 0; i < number_of_parallel_requests; i++) {
+ let chan = makeChan(httpsOrigin + "20000");
+ chan.asyncOpen(listener);
+ do_test_pending();
}
-);
+}
+
+// A request cancelled by a server.
+function test_request_cancelled_by_server() {
+ dump("test_request_cancelled_by_server()\n");
+
+ let listener = new Http3CheckListener();
+ listener.expectedStatus = Cr.NS_ERROR_NET_INTERRUPT;
+ listener.expectedRoute = h3Route;
+ let chan = makeChan(httpsOrigin + "RequestCancelled");
+ chan.asyncOpen(listener);
+ do_test_pending();
+}
+
+let CancelRequestListener = function () {};
+
+CancelRequestListener.prototype = new Http3CheckListener();
+
+CancelRequestListener.prototype.expectedStatus = Cr.NS_ERROR_ABORT;
+
+CancelRequestListener.prototype.onStartRequest = function testOnStartRequest(
+ request
+) {
+ Assert.ok(request instanceof Ci.nsIHttpChannel);
+
+ Assert.equal(Components.isSuccessCode(request.status), true);
+ request.cancel(Cr.NS_ERROR_ABORT);
+};
+
+// Cancel stream after OnStartRequest.
+function test_stream_cancelled_by_necko() {
+ dump("test_stream_cancelled_by_necko()\n");
+
+ let listener = new CancelRequestListener();
+ listener.expectedRoute = h3Route;
+ let chan = makeChan(httpsOrigin + "20000");
+ chan.asyncOpen(listener);
+ do_test_pending();
+}
+
+// Multiple requests, one gets cancelled by the server, the other should finish normally.
+function test_multiple_request_one_is_cancelled() {
+ dump("test_multiple_request_one_is_cancelled()\n");
+
+ let listener = new MultipleListener();
+ listener.number_of_parallel_requests = number_of_parallel_requests;
+ listener.with_error = Cr.NS_ERROR_NET_INTERRUPT;
+ listener.expectedRoute = h3Route;
+
+ for (let i = 0; i < number_of_parallel_requests; i++) {
+ let uri = httpsOrigin + "20000";
+ if (i == 4) {
+ // Add a request that will be cancelled by the server.
+ uri = httpsOrigin + "RequestCancelled";
+ }
+ let chan = makeChan(uri);
+ chan.asyncOpen(listener);
+ do_test_pending();
+ }
+}
+
+// Multiple requests, one gets cancelled by us, the other should finish normally.
+function test_multiple_request_one_is_cancelled_by_necko() {
+ dump("test_multiple_request_one_is_cancelled_by_necko()\n");
+
+ let listener = new MultipleListener();
+ listener.number_of_parallel_requests = number_of_parallel_requests;
+ listener.with_error = Cr.NS_ERROR_ABORT;
+ listener.expectedRoute = h3Route;
+ for (let i = 0; i < number_of_parallel_requests; i++) {
+ let chan = makeChan(httpsOrigin + "20000");
+ if (i == 4) {
+ // MultipleListener will cancel request with this header.
+ chan.setRequestHeader("CancelMe", "true", false);
+ }
+ chan.asyncOpen(listener);
+ do_test_pending();
+ }
+}
+
+let PostListener = function () {};
+
+PostListener.prototype = new Http3CheckListener();
+
+PostListener.prototype.onDataAvailable = function (request, stream, off, cnt) {
+ this.onDataAvailableFired = true;
+ read_stream(stream, cnt);
+};
+
+// Support for doing a POST
+function do_post(content, chan, listener, method) {
+ let stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
+ Ci.nsIStringInputStream
+ );
+ stream.setByteStringData(content);
+
+ let uchan = chan.QueryInterface(Ci.nsIUploadChannel);
+ uchan.setUploadStream(stream, "text/plain", stream.available());
+
+ chan.requestMethod = method;
+
+ chan.asyncOpen(listener);
+}
+
+// Test a simple POST
+function test_post() {
+ dump("test_post()");
+ let chan = makeChan(httpsOrigin + "post");
+ let listener = new PostListener();
+ listener.expectedRoute = h3Route;
+ do_post(post, chan, listener, "POST");
+ do_test_pending();
+}
+
+// Test a simple PATCH
+function test_patch() {
+ dump("test_patch()");
+ let chan = makeChan(httpsOrigin + "patch");
+ let listener = new PostListener();
+ listener.expectedRoute = h3Route;
+ do_post(post, chan, listener, "PATCH");
+ do_test_pending();
+}
+
+// Test alt-svc for http (without s)
+function test_http_alt_svc() {
+ dump("test_http_alt_svc()\n");
+ // Skip this test on Android because the httpOrigin (http://foo.example.com)
+ // is on 127.0.0.1, while the http3Server (https://foo.example.com) is
+ // on 10.0.2.2. Currently, we can't change the IP mapping dynamically.
+ if (mozinfo.os == "android") {
+ current_test++;
+ run_next_test();
+ return;
+ }
+ do_test_pending();
+ doTest(httpOrigin + "http3-test", h3Route, h3AltSvc);
+}
+
+let SlowReceiverListener = function () {};
+
+SlowReceiverListener.prototype = new Http3CheckListener();
+SlowReceiverListener.prototype.count = 0;
+
+SlowReceiverListener.prototype.onDataAvailable = function (
+ request,
+ stream,
+ off,
+ cnt
+) {
+ this.onDataAvailableFired = true;
+ this.count += cnt;
+ read_stream(stream, cnt);
+};
+
+SlowReceiverListener.prototype.onStopRequest = function (request, status) {
+ Assert.equal(status, this.expectedStatus);
+ Assert.equal(this.count, 10000000);
+ let routed = "NA";
+ try {
+ routed = request.getRequestHeader("Alt-Used");
+ } catch (e) {}
+ dump("routed is " + routed + "\n");
+
+ Assert.equal(routed, this.expectedRoute);
+
+ if (Components.isSuccessCode(this.expectedStatus)) {
+ let httpVersion = "";
+ try {
+ httpVersion = request.protocolVersion;
+ } catch (e) {}
+ Assert.equal(httpVersion, "h3");
+ Assert.equal(this.onDataAvailableFired, true);
+ }
+ run_next_test();
+ do_test_finished();
+};
+
+function test_slow_receiver() {
+ dump("test_slow_receiver()\n");
+ let chan = makeChan(httpsOrigin + "10000000");
+ let listener = new SlowReceiverListener();
+ listener.expectedRoute = h3Route;
+ chan.asyncOpen(listener);
+ do_test_pending();
+ chan.suspend();
+ do_timeout(1000, chan.resume);
+}
+
+let CheckFallbackListener = function () {};
+
+CheckFallbackListener.prototype = {
+ onStartRequest: function testOnStartRequest(request) {
+ Assert.ok(request instanceof Ci.nsIHttpChannel);
+
+ Assert.equal(request.status, Cr.NS_OK);
+ Assert.equal(request.responseStatus, 200);
+ },
+
+ onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) {
+ read_stream(stream, cnt);
+ },
+
+ onStopRequest: function testOnStopRequest(request, status) {
+ Assert.equal(status, Cr.NS_OK);
+ let routed = "NA";
+ try {
+ routed = request.getRequestHeader("Alt-Used");
+ } catch (e) {}
+ dump("routed is " + routed + "\n");
+
+ Assert.equal(routed, "0");
+
+ let httpVersion = "";
+ try {
+ httpVersion = request.protocolVersion;
+ } catch (e) {}
+ Assert.equal(httpVersion, "http/1.1");
+ run_next_test();
+ do_test_finished();
+ },
+};
+
+// Server cancels request with VersionFallback.
+function test_version_fallback() {
+ dump("test_version_fallback()\n");
+
+ let chan = makeChan(httpsOrigin + "VersionFallback");
+ let listener = new CheckFallbackListener();
+ chan.asyncOpen(listener);
+ do_test_pending();
+}
-add_task(async function test_slow_receiver() {
- await do_test_slow_receiver(httpsOrigin, h3Route);
-});
-
-// This test should be at the end, because it will close http3
-// connection and the transaction will switch to already existing http2
-// connection.
-// TODO: Bug 1582667 should try to fix issue with connection being closed.
-add_task(async function test_version_fallback() {
- await do_test_version_fallback(httpsOrigin);
-});
+function testsDone() {
+ prefs.clearUserPref("network.http.http3.enable");
+ prefs.clearUserPref("network.dns.localDomains");
+ prefs.clearUserPref("network.proxy.allow_hijacking_localhost");
+ prefs.clearUserPref("network.http.altsvc.oe");
+ dump("testDone\n");
+ do_test_pending();
+ h1Server.stop(do_test_finished);
+}
diff --git a/netwerk/test/unit/test_http3_with_proxy.js b/netwerk/test/unit/test_http3_with_proxy.js
@@ -1,180 +0,0 @@
-"use strict";
-
-/* import-globals-from http3_common.js */
-
-const { Http3ProxyFilter, NodeHTTP2ProxyServer } = ChromeUtils.importESModule(
- "resource://testing-common/NodeServer.sys.mjs"
-);
-
-// Max concurent stream number in neqo is 100.
-// Openning 120 streams will test queuing of streams.
-let number_of_parallel_requests = 120;
-let h3Route;
-let httpsOrigin;
-let h3AltSvc;
-let h3Port;
-let h3ServerDomain;
-let prefs;
-
-let pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService();
-let proxyHost;
-let proxyPort;
-let proxyFilter;
-
-add_setup(async function () {
- let h2Port = Services.env.get("MOZHTTP2_PORT");
- Assert.notEqual(h2Port, null);
- Assert.notEqual(h2Port, "");
- h3Port = Services.env.get("MOZHTTP3_PORT");
- Assert.notEqual(h3Port, null);
- Assert.notEqual(h3Port, "");
- h3AltSvc = ":" + h3Port;
- h3ServerDomain = "foo.example.com";
- h3Route = `${h3ServerDomain}:${h3Port}`;
- do_get_profile();
- prefs = Services.prefs;
-
- prefs.setBoolPref("network.http.http3.enable", true);
- // We always resolve elements of localDomains as it's hardcoded without the
- // following pref:
- prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true);
- prefs.setBoolPref("network.http.altsvc.oe", true);
-
- if (mozinfo.os == "android") {
- // Set necessary prefs to make Firefox connect to the http3Server on the
- // host machine.
- prefs.setCharPref("network.dns.localDomains", "");
- const overrideService = Cc[
- "@mozilla.org/network/native-dns-override;1"
- ].getService(Ci.nsINativeDNSResolverOverride);
- overrideService.addIPOverride(h3ServerDomain, "10.0.2.2");
- prefs.setCharPref(
- "network.http.http3.alt-svc-mapping-for-testing",
- `${h3ServerDomain};h3=:${h3Port}`
- );
- } else {
- prefs.setCharPref(
- "network.dns.localDomains",
- "foo.example.com, alt1.example.com"
- );
- }
-
- // The certificate for the http3server server is for foo.example.com and
- // is signed by http2-ca.pem so add that cert to the trust list as a
- // signing cert.
- 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");
- httpsOrigin = `https://${h3ServerDomain}:${h2Port}/`;
-
- proxyHost = "alt1.example.com";
- proxyPort = Services.env.get("MOZHTTP3_PORT_MASQUE");
- 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);
-
- registerCleanupFunction(() => {
- prefs.clearUserPref("network.http.http3.enable");
- prefs.clearUserPref("network.dns.localDomains");
- prefs.clearUserPref("network.proxy.allow_hijacking_localhost");
- prefs.clearUserPref("network.http.altsvc.oe");
- prefs.clearUserPref("network.http.http3.alt-svc-mapping-for-testing");
- pps.unregisterFilter(proxyFilter);
- if (mozinfo.os == "android") {
- const overrideService = Cc[
- "@mozilla.org/network/native-dns-override;1"
- ].getService(Ci.nsINativeDNSResolverOverride);
- overrideService.clearOverrides();
- }
- });
-});
-
-add_task(async function test_https_alt_svc() {
- await waitForHttp3Route(httpsOrigin + "http3-test", h3Route, h3AltSvc, {
- delayMs: 500,
- });
-});
-
-add_task(async function test_multiple_requests() {
- await do_test_multiple_requests(
- number_of_parallel_requests,
- h3Route,
- httpsOrigin
- );
-});
-
-add_task(async function test_request_cancelled_by_server() {
- await do_test_request_cancelled_by_server(h3Route, httpsOrigin);
-});
-
-add_task(async function test_stream_cancelled_by_necko() {
- await do_test_stream_cancelled_by_necko(h3Route, httpsOrigin);
-});
-
-add_task(async function test_multiple_request_one_is_cancelled() {
- await do_test_multiple_request_one_is_cancelled(
- number_of_parallel_requests,
- h3Route,
- httpsOrigin
- );
-});
-
-add_task(async function test_multiple_request_one_is_cancelled_by_necko() {
- await do_test_multiple_request_one_is_cancelled_by_necko(
- number_of_parallel_requests,
- h3Route,
- httpsOrigin
- );
-});
-
-add_task(async function test_post() {
- await do_test_post(httpsOrigin, h3Route);
-});
-
-add_task(async function test_patch() {
- await do_test_patch(httpsOrigin, h3Route);
-});
-
-add_task(
- {
- // Skip this test on Android because the httpOrigin (http://foo.example.com)
- // is on 127.0.0.1, while the http3Server (https://foo.example.com) is
- // on 10.0.2.2. Currently, we can't change the IP mapping dynamically.
- skip_if: () => mozinfo.os == "android",
- },
- async function test_http_alt_svc() {
- setup_h1_server(h3ServerDomain);
- await waitForHttp3Route(httpOrigin + "http3-test", h3Route, h3AltSvc, {
- delayMs: 500,
- });
- }
-);
-
-add_task(async function test_slow_receiver() {
- await do_test_slow_receiver(httpsOrigin, h3Route);
-});
-
-// This test should be at the end, because it will close http3
-// connection and the transaction will switch to already existing http2
-// connection.
-// TODO: Bug 1582667 should try to fix issue with connection being closed.
-add_task(async function test_version_fallback() {
- let proxy = new NodeHTTP2ProxyServer();
- await proxy.startWithoutProxyFilter(proxyPort);
- registerCleanupFunction(async () => {
- await proxy.stop();
- });
- Assert.equal(proxyPort, proxy.port());
- info(`proxy port=${proxy.port()}\n`);
-
- await do_test_version_fallback(httpsOrigin);
-});
diff --git a/netwerk/test/unit/xpcshell.toml b/netwerk/test/unit/xpcshell.toml
@@ -27,7 +27,6 @@ support-files = [
"test_http3_prio_helpers.js",
"http2_test_common.js",
"http3_proxy_common.js",
- "http3_common.js",
]
# dom.serviceWorkers.enabled is currently set to false in StaticPrefList.yaml
@@ -710,17 +709,6 @@ 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_http3.js"]
-head = "head_cookies.js head_channels.js head_cache.js head_http3.js http3_common.js"
-run-sequentially = ["true"] # http3server
-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_with_proxy.js"]
-head = "head_cookies.js head_channels.js head_cache.js head_http3.js http3_common.js"
run-sequentially = ["true"] # http3server
skip-if = [
"os == 'android' && os_version == '14' && processor == 'x86_64'", # Bug 1982955