tor-browser

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

commit 63760f73c8971618240cbd485304f21bc01f1fe0
parent 4aafd5370851211ca68948717799a3b0c8037614
Author: Hubert Boma Manilla <hmanilla@mozilla.com>
Date:   Fri, 19 Dec 2025 17:14:37 +0000

Bug 2004329 - [devtools] Display webTransport session request in the netmonitor r=devtools-reviewers,nchevobbe

This is the initial patch to displays a webtransport request in the netmonitor
when a new webtransport connection is created.

A good demo project for manual testing is https://github.com/BiagioFesta/wtransport

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

Diffstat:
Mdevtools/client/netmonitor/src/connector/index.js | 27+++++++++++++++++----------
Mdevtools/server/actors/resources/index.js | 4++++
Mdevtools/server/actors/resources/webtransport.js | 27++++++++++++++++++++-------
Mdevtools/server/actors/watcher/session-context.js | 1+
Mdevtools/shared/commands/resource/resource-command.js | 1+
Mdevtools/shared/network-observer/NetworkUtils.sys.mjs | 1+
6 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/devtools/client/netmonitor/src/connector/index.js b/devtools/client/netmonitor/src/connector/index.js @@ -66,6 +66,16 @@ class Connector { TYPES.SERVER_SENT_EVENT, ]; + get networkResources() { + const networkResources = Array.from(Connector.NETWORK_RESOURCES); + if ( + Services.prefs.getBoolPref("devtools.netmonitor.features.webtransport") + ) { + networkResources.push(TYPES.WEBTRANSPORT); + } + return networkResources; + } + get currentTarget() { return this.commands.targetCommand.targetFront; } @@ -161,7 +171,7 @@ class Connector { if (isExplicitClear) { // Only clear the resources if the clear was initiated explicitly by the // UI, in other cases (eg navigation) the server handles the cleanup. - this.commands.resourceCommand.clearResources(Connector.NETWORK_RESOURCES); + this.commands.resourceCommand.clearResources(this.networkResources); this.emitForTests("clear-network-resources"); } @@ -171,7 +181,7 @@ class Connector { pause() { return this.commands.resourceCommand.unwatchResources( - Connector.NETWORK_RESOURCES, + this.networkResources, { onAvailable: this.onResourceAvailable, onUpdated: this.onResourceUpdated, @@ -180,14 +190,11 @@ class Connector { } resume(ignoreExistingResources = true) { - return this.commands.resourceCommand.watchResources( - Connector.NETWORK_RESOURCES, - { - onAvailable: this.onResourceAvailable, - onUpdated: this.onResourceUpdated, - ignoreExistingResources, - } - ); + return this.commands.resourceCommand.watchResources(this.networkResources, { + onAvailable: this.onResourceAvailable, + onUpdated: this.onResourceUpdated, + ignoreExistingResources, + }); } async onResourceAvailable(resources, { areExistingResources }) { diff --git a/devtools/server/actors/resources/index.js b/devtools/server/actors/resources/index.js @@ -25,6 +25,7 @@ const TYPES = { JSTRACER_TRACE: "jstracer-trace", JSTRACER_STATE: "jstracer-state", WEBSOCKET: "websocket", + WEBTRANSPORT: "webtransport", // storage types CACHE_STORAGE: "Cache", @@ -116,6 +117,9 @@ const FrameTargetResources = augmentResourceDictionary({ [TYPES.WEBSOCKET]: { path: "devtools/server/actors/resources/websockets", }, + [TYPES.WEBTRANSPORT]: { + path: "devtools/server/actors/resources/webtransport", + }, }); // Process target resources are spawned via a Process Target Actor. diff --git a/devtools/server/actors/resources/webtransport.js b/devtools/server/actors/resources/webtransport.js @@ -10,12 +10,19 @@ const webTransportEventService = Cc[ class WebTransportWatcher { constructor() { - this.windowIds = new Set(); + this.windowIds = new Map(); this.abortController = new AbortController(); this.onWindowReady = this.onWindowReady.bind(this); this.onWindowDestroy = this.onWindowDestroy.bind(this); } + static createResource(wtMessageType, eventParams) { + return { + wtMessageType, + ...eventParams, + }; + } + watch(targetActor, { onAvailable }) { this.targetActor = targetActor; this.onAvailable = onAvailable; @@ -47,14 +54,18 @@ class WebTransportWatcher { startListening(innerWindowId) { if (!this.windowIds.has(innerWindowId)) { - this.windowIds.add(innerWindowId); - webTransportEventService.addListener(innerWindowId, this); + const listener = { + // methods for the webTransportEventService + webTransportSessionCreated: () => {}, + webTransportSessionClosed: () => {}, + }; + this.windowIds.set(innerWindowId, listener); + webTransportEventService.addListener(innerWindowId, listener); } } stopListening(innerWindowId) { if (this.windowIds.has(innerWindowId)) { - this.windowIds.delete(innerWindowId); if (!webTransportEventService.hasListenerFor(innerWindowId)) { // The listener might have already been cleaned up on `window-destroy`. console.warn( @@ -62,7 +73,11 @@ class WebTransportWatcher { ); return; } - webTransportEventService.removeListener(innerWindowId, this); + webTransportEventService.removeListener( + innerWindowId, + this.windowIds.get(innerWindowId) + ); + this.windowIds.delete(innerWindowId); } } @@ -72,8 +87,6 @@ class WebTransportWatcher { this.stopListening(id); } } - - // TODO: methods for the webTransportEventService } module.exports = WebTransportWatcher; diff --git a/devtools/server/actors/watcher/session-context.js b/devtools/server/actors/watcher/session-context.js @@ -201,6 +201,7 @@ function getWatcherSupportedResources(_type) { [Resources.TYPES.THREAD_STATE]: true, [Resources.TYPES.SERVER_SENT_EVENT]: true, [Resources.TYPES.WEBSOCKET]: true, + [Resources.TYPES.WEBTRANSPORT]: true, [Resources.TYPES.JSTRACER_TRACE]: true, [Resources.TYPES.JSTRACER_STATE]: true, [Resources.TYPES.LAST_PRIVATE_CONTEXT_EXIT]: true, diff --git a/devtools/shared/commands/resource/resource-command.js b/devtools/shared/commands/resource/resource-command.js @@ -1287,6 +1287,7 @@ ResourceCommand.TYPES = ResourceCommand.prototype.TYPES = { STYLESHEET: "stylesheet", NETWORK_EVENT: "network-event", WEBSOCKET: "websocket", + WEBTRANSPORT: "webtransport", COOKIE: "cookies", LOCAL_STORAGE: "local-storage", SESSION_STORAGE: "session-storage", diff --git a/devtools/shared/network-observer/NetworkUtils.sys.mjs b/devtools/shared/network-observer/NetworkUtils.sys.mjs @@ -76,6 +76,7 @@ const LOAD_CAUSE_STRINGS = { [Ci.nsIContentPolicy.TYPE_FONT]: "font", [Ci.nsIContentPolicy.TYPE_MEDIA]: "media", [Ci.nsIContentPolicy.TYPE_WEBSOCKET]: "websocket", + [Ci.nsIContentPolicy.TYPE_WEB_TRANSPORT]: "webtransport", [Ci.nsIContentPolicy.TYPE_CSP_REPORT]: "csp", [Ci.nsIContentPolicy.TYPE_XSLT]: "xslt", [Ci.nsIContentPolicy.TYPE_BEACON]: "beacon",