tor-browser

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

commit fc7213881555a9e3acb8290530f3a2a29697f8ff
parent 10ffdc9d9c5559351a0380ed414301917130286d
Author: Hubert Boma Manilla <hmanilla@mozilla.com>
Date:   Mon, 22 Dec 2025 04:06:31 +0000

Bug 1960549 - [devtools] Add resource watcher for webtransport events r=devtools-reviewers,nchevobbe

This adds the resource watcher for webtransport events.

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

Diffstat:
Mdevtools/server/actors/resources/moz.build | 1+
Adevtools/server/actors/resources/webtransport.js | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdevtools/server/tests/chrome/chrome.toml | 2++
Adevtools/server/tests/chrome/test_webtransport-listeners.html | 32++++++++++++++++++++++++++++++++
4 files changed, 114 insertions(+), 0 deletions(-)

diff --git a/devtools/server/actors/resources/moz.build b/devtools/server/actors/resources/moz.build @@ -38,6 +38,7 @@ DevToolsModules( "stylesheets.js", "thread-states.js", "websockets.js", + "webtransport.js", ) with Files("*-messages.js"): diff --git a/devtools/server/actors/resources/webtransport.js b/devtools/server/actors/resources/webtransport.js @@ -0,0 +1,79 @@ +/* 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"; + +const webTransportEventService = Cc[ + "@mozilla.org/webtransportevent/service;1" +].getService(Ci.nsIWebTransportEventService); + +class WebTransportWatcher { + constructor() { + this.windowIds = new Set(); + this.abortController = new AbortController(); + this.onWindowReady = this.onWindowReady.bind(this); + this.onWindowDestroy = this.onWindowDestroy.bind(this); + } + + watch(targetActor, { onAvailable }) { + this.targetActor = targetActor; + this.onAvailable = onAvailable; + + for (const window of this.targetActor.windows) { + const { innerWindowId } = window.windowGlobalChild; + this.startListening(innerWindowId); + } + + // On navigate/reload we should re-start listening with the new `innerWindowID` + if (!this.targetActor.followWindowGlobalLifeCycle) { + this.targetActor.on("window-ready", this.onWindowReady, { + signal: this.abortController.signal, + }); + this.targetActor.on("window-destroyed", this.onWindowDestroy, { + signal: this.abortController.signal, + }); + } + } + + onWindowReady({ window }) { + const { innerWindowId } = window.windowGlobalChild; + this.startListening(innerWindowId); + } + + onWindowDestroy({ id }) { + this.stopListening(id); + } + + startListening(innerWindowId) { + if (!this.windowIds.has(innerWindowId)) { + this.windowIds.add(innerWindowId); + webTransportEventService.addListener(innerWindowId, this); + } + } + + 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( + "Already stopped listening to webtransport events for this window." + ); + return; + } + webTransportEventService.removeListener(innerWindowId, this); + } + } + + destroy() { + this.abortController.abort(); + for (const id of this.windowIds) { + this.stopListening(id); + } + } + + // TODO: methods for the webTransportEventService +} + +module.exports = WebTransportWatcher; diff --git a/devtools/server/tests/chrome/chrome.toml b/devtools/server/tests/chrome/chrome.toml @@ -147,3 +147,5 @@ support-files = [ ["test_unsafeDereference.html"] ["test_webconsole-node-grip.html"] + +["test_webtransport-listeners.html"] diff --git a/devtools/server/tests/chrome/test_webtransport-listeners.html b/devtools/server/tests/chrome/test_webtransport-listeners.html @@ -0,0 +1,32 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test the WebTransport watcher </title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script class="testbody" type="text/javascript"> + 'use strict'; + const { require } = ChromeUtils.importESModule("resource://devtools/shared/loader/Loader.sys.mjs"); + const WebTransportWatcher = require("devtools/server/actors/resources/webtransport.js"); + var service = Cc["@mozilla.org/webtransportevent/service;1"] + .getService(Ci.nsIWebTransportEventService); + ok(!!service, "We have the nsIWebTransportEventService"); + + var innerWindowId = window.windowGlobalChild.innerWindowId; + ok(innerWindowId, "We have a valid innerWindowID: " + innerWindowId); + + const watcher = new WebTransportWatcher(); + + watcher.startListening(innerWindowId); + ok(service.hasListenerFor(innerWindowId), "Service has listener for the window"); + + watcher.stopListening(innerWindowId); + ok(!service.hasListenerFor(innerWindowId), "Service no longer has a listener for the window"); + + // Make sure this does not throw if the listener does not exist. + watcher.stopListening(innerWindowId); +</script> +</body> +</html>