tor-browser

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

commit 77cd2bd4edabe1d58c087483bf725e198014ba81
parent 26058b267b89eaf03dbf6cb3d8e38d25e796f773
Author: Valentin Gosu <valentin.gosu@gmail.com>
Date:   Tue, 25 Nov 2025 14:42:47 +0000

Bug 2001617 - Add WebSocket with maque proxy test r=necko-reviewers,kershaw

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

Diffstat:
Mnetwerk/test/unit/http3_proxy_common.js | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mnetwerk/test/unit/test_http3_proxy.js | 1+
Mnetwerk/test/unit/test_websocket_proxy.js | 64++++++++++++++++++++++++++++++++++++++++++----------------------
Mnetwerk/test/unit/xpcshell.toml | 1+
4 files changed, 110 insertions(+), 22 deletions(-)

diff --git a/netwerk/test/unit/http3_proxy_common.js b/netwerk/test/unit/http3_proxy_common.js @@ -16,6 +16,8 @@ const { NodeHTTPSServer, NodeHTTP2Server, NodeHTTP2ProxyServer, + NodeWebSocketHttp2Server, + WebSocketConnection, } = ChromeUtils.importESModule("resource://testing-common/NodeServer.sys.mjs"); function makeChan(uri) { @@ -431,6 +433,70 @@ async function test_http_connect_fallback() { await server.stop(); } +/** + * Helper function to open a WebSocket connection + */ +async function wsChannelOpenPromise(url, msg) { + let conn = new WebSocketConnection(); + let statusObj = await Promise.race([conn.open(url), conn.finished()]); + if (statusObj && statusObj.status != Cr.NS_OK) { + return [statusObj.status, ""]; + } + let finalStatusPromise = conn.finished(); + conn.send(msg); + let res = await conn.receiveMessages(); + conn.close(); + let finalStatus = await finalStatusPromise; + return [finalStatus.status, res]; +} + +/** + * Test WebSocket through H3 proxy using H2 WebSocket server + */ +async function test_http_connect_websocket() { + info("Running test_http_connect_websocket"); + Services.prefs.setBoolPref("network.http.http2.websockets", true); + + let wss = new NodeWebSocketHttp2Server(); + await wss.start(); + + registerCleanupFunction(async () => { + await wss.stop(); + }); + + Assert.notEqual(wss.port(), null); + await wss.registerMessageHandler((data, ws) => { + ws.send(data); + }); + + let url = `wss://alt1.example.com:${wss.port()}`; + const msg = "test h2 websocket through h3 proxy"; + let [status, res] = await wsChannelOpenPromise(url, msg); + Assert.equal(status, Cr.NS_OK); + Assert.deepEqual(res, [msg]); + + // Test multiple messages + let conn = new WebSocketConnection(); + await conn.open(url); + conn.send("message1"); + let mess1 = await conn.receiveMessages(); + Assert.deepEqual(mess1, ["message1"]); + + conn.send("message2"); + conn.send("message3"); + let mess2 = []; + while (mess2.length < 2) { + mess2 = mess2.concat(await conn.receiveMessages()); + } + Assert.deepEqual(mess2, ["message2", "message3"]); + + conn.close(); + let { status: finalStatus } = await conn.finished(); + Assert.equal(finalStatus, Cr.NS_OK); + + await wss.stop(); +} + async function test_inner_connection_fallback() { info("Running test_inner_connection_fallback"); let h3Port = Services.env.get("MOZHTTP3_PORT_NO_RESPONSE"); diff --git a/netwerk/test/unit/test_http3_proxy.js b/netwerk/test/unit/test_http3_proxy.js @@ -20,6 +20,7 @@ add_task(test_http_connect_invalid_host); add_task(test_concurrent_http_connect_tunnels); // TODO: Proxy needs to close the stream properly when socket failures occur // add_task(test_http_connect_stream_closure); +add_task(test_http_connect_websocket); add_task(test_connect_udp); add_task(test_http_connect_fallback); add_task(test_inner_connection_fallback); diff --git a/netwerk/test/unit/test_websocket_proxy.js b/netwerk/test/unit/test_websocket_proxy.js @@ -4,18 +4,24 @@ "use strict"; +/* import-globals-from http3_proxy_common.js */ + const { NodeWebSocketPlainServer, NodeWebSocketServer, - NodeWebSocketHttp2Server, NodeHTTPProxyServer, NodeHTTPSProxyServer, - NodeHTTP2ProxyServer, - WebSocketConnection, - with_node_servers, } = ChromeUtils.importESModule("resource://testing-common/NodeServer.sys.mjs"); -async function channelOpenPromise(url, msg) { +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +add_setup(async function setup() { + do_get_profile(); +}); + +async function wsChannelOpen(url, msg) { let conn = new WebSocketConnection(); let statusObj = await Promise.race([conn.open(url), conn.finished()]); if (statusObj && statusObj.status != Cr.NS_OK) { @@ -39,23 +45,27 @@ registerCleanupFunction(() => { Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost"); }); -async function do_ws_requests(expectedProxyType) { - await with_node_servers( - [NodeWebSocketPlainServer, NodeWebSocketServer, NodeWebSocketHttp2Server], - async server => { - Assert.notEqual(server.port(), null); - await server.registerMessageHandler((data, ws) => { - ws.send(data); - }); - - let url = `${server.protocol()}://localhost:${server.port()}`; - const msg = `test ${server.constructor.name} with proxy`; - let [status, res, proxyType] = await channelOpenPromise(url, msg); - Assert.equal(status, Cr.NS_OK); - Assert.deepEqual(res, [msg]); - Assert.equal(proxyType, expectedProxyType, "WebSocket should use proxy"); - } - ); +async function do_ws_requests( + expectedProxyType, + servers = [ + NodeWebSocketPlainServer, + NodeWebSocketServer, + NodeWebSocketHttp2Server, + ] +) { + await with_node_servers(servers, async server => { + Assert.notEqual(server.port(), null); + await server.registerMessageHandler((data, ws) => { + ws.send(data); + }); + + let url = `${server.protocol()}://localhost:${server.port()}`; + const msg = `test ${server.constructor.name} with proxy`; + let [status, res, proxyType] = await wsChannelOpen(url, msg); + Assert.equal(status, Cr.NS_OK); + Assert.deepEqual(res, [msg]); + Assert.equal(proxyType, expectedProxyType, "WebSocket should use proxy"); + }); } add_task(async function test_http_proxy() { @@ -93,3 +103,13 @@ add_task(async function test_http2_proxy() { await proxy.stop(); }); + +// Skipped on Android due to H3 proxy server not working - Bug 1982955 +add_task( + { skip_if: () => AppConstants.platform == "android" }, + async function test_masque_proxy() { + await setup_http3_proxy(); + + await do_ws_requests("masque"); + } +); diff --git a/netwerk/test/unit/xpcshell.toml b/netwerk/test/unit/xpcshell.toml @@ -1604,6 +1604,7 @@ run-sequentially = ["true"] # node server exceptions dont replay well ["test_websocket_offline.js"] ["test_websocket_proxy.js"] +head = "head_cookies.js head_channels.js head_cache.js head_http3.js http3_proxy_common.js" ["test_websocket_server.js"] run-sequentially = ["true"] # node server exceptions dont replay well