tor-browser

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

commit 1928932c32104ec5a4171f7d4b19f3b333834540
parent adb38904a5a5714d61cc62c4cc4bb394e1a9c553
Author: Hubert Boma Manilla <hmanilla@mozilla.com>
Date:   Mon, 10 Nov 2025 12:13:02 +0000

Bug 1999236 - Add the WebTransport Event Service and API's for managing listeners r=necko-reviewers,layout-reviewers,kershaw,emilio

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

Diffstat:
Adom/webtransport/test/chrome.toml | 14++++++++++++++
Mdom/webtransport/test/moz.build | 4++++
Adom/webtransport/test/test_webtransporteventservice_basic.html | 30++++++++++++++++++++++++++++++
Mlayout/build/components.conf | 8++++++++
Anetwerk/protocol/webtransport/WebTransportEventService.cpp | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Anetwerk/protocol/webtransport/WebTransportEventService.h | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mnetwerk/protocol/webtransport/moz.build | 3+++
Anetwerk/protocol/webtransport/nsIWebTransportEventService.idl | 24++++++++++++++++++++++++
8 files changed, 304 insertions(+), 0 deletions(-)

diff --git a/dom/webtransport/test/chrome.toml b/dom/webtransport/test/chrome.toml @@ -0,0 +1,14 @@ +# 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/. + +[DEFAULT] +run-if = ["http3"] +prefs = [ + "network.dns.localDomains=foo.example.com", + "network.webtransport.enabled=true", + "network.http.http3.enabled=true" +] + +["test_webtransporteventservice_basic.html"] +scheme = ["https"] diff --git a/dom/webtransport/test/moz.build b/dom/webtransport/test/moz.build @@ -7,3 +7,7 @@ TEST_DIRS += [ "xpcshell", ] + +MOCHITEST_CHROME_MANIFESTS += [ + "chrome.toml", +] diff --git a/dom/webtransport/test/test_webtransporteventservice_basic.html b/dom/webtransport/test/test_webtransporteventservice_basic.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>WebTransportevent service basic test</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"> + 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); + + var listener = { + QueryInterface: ChromeUtils.generateQI(["nsIWebTransportEventListener"]), + }; + + service.addListener(innerWindowId, listener); + ok(true, "Listener added"); + ok(service.hasListenerFor(innerWindowId), "hasListenerFor(innerId) should be true"); + + service.removeListener(innerWindowId, listener); + ok(true, "Listener removed"); + ok(!service.hasListenerFor(innerWindowId), "hasListenerFor(innerId) should be false"); +</script> +</body> +</html> diff --git a/layout/build/components.conf b/layout/build/components.conf @@ -441,6 +441,14 @@ Classes = [ 'headers': ['mozilla/dom/EventSourceEventService.h'], 'constructor': 'mozilla::dom::EventSourceEventService::GetOrCreate', }, + { + 'cid': '{54e6b9d6-248c-4eb0-81b8-e72f04067f3c}', + 'contract_ids': ['@mozilla.org/webtransportevent/service;1'], + 'singleton': True, + 'type': 'mozilla::net::WebTransportEventService', + 'headers': ['mozilla/net/WebTransportEventService.h'], + 'constructor': 'mozilla::net::WebTransportEventService::GetOrCreate', + }, ] if defined('MOZ_WEBSPEECH'): diff --git a/netwerk/protocol/webtransport/WebTransportEventService.cpp b/netwerk/protocol/webtransport/WebTransportEventService.cpp @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "WebTransportEventService.h" +#include "nsThreadUtils.h" +#include "nsIObserverService.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/Services.h" +#include "nsISupportsPrimitives.h" + +namespace mozilla { +namespace net { + +namespace { + +StaticRefPtr<WebTransportEventService> gWebTransportEventService; + +} // anonymous namespace + +/* static */ +already_AddRefed<WebTransportEventService> +WebTransportEventService::GetOrCreate() { + MOZ_ASSERT(NS_IsMainThread()); + + if (!gWebTransportEventService) { + gWebTransportEventService = new WebTransportEventService(); + } + + RefPtr<WebTransportEventService> service = gWebTransportEventService.get(); + return service.forget(); +} + +NS_INTERFACE_MAP_BEGIN(WebTransportEventService) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebTransportEventService) + NS_INTERFACE_MAP_ENTRY(nsIObserver) + NS_INTERFACE_MAP_ENTRY(nsIWebTransportEventService) +NS_INTERFACE_MAP_END + +NS_IMPL_ADDREF(WebTransportEventService) +NS_IMPL_RELEASE(WebTransportEventService) + +WebTransportEventService::WebTransportEventService() : mCountListeners(0) { + MOZ_ASSERT(NS_IsMainThread()); + + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (obs) { + obs->AddObserver(this, "xpcom-shutdown", false); + obs->AddObserver(this, "inner-window-destroyed", false); + } +} + +WebTransportEventService::~WebTransportEventService() { + MOZ_ASSERT(NS_IsMainThread()); +} + +NS_IMETHODIMP +WebTransportEventService::AddListener(uint64_t aInnerWindowID, + nsIWebTransportEventListener* aListener) { + MOZ_ASSERT(NS_IsMainThread()); + + if (!aListener) { + return NS_ERROR_INVALID_ARG; + } + + ++mCountListeners; + + WindowListener* listener = mWindows.GetOrInsertNew(aInnerWindowID); + + listener->mListeners.AppendElement(aListener); + + return NS_OK; +} + +NS_IMETHODIMP +WebTransportEventService::RemoveListener( + uint64_t aInnerWindowID, nsIWebTransportEventListener* aListener) { + MOZ_ASSERT(NS_IsMainThread()); + + if (!aListener) { + return NS_ERROR_INVALID_ARG; + } + + WindowListener* listener = mWindows.Get(aInnerWindowID); + if (!listener) { + return NS_ERROR_FAILURE; + } + + if (!listener->mListeners.RemoveElement(aListener)) { + return NS_ERROR_FAILURE; + } + + // The last listener for this window. + if (listener->mListeners.IsEmpty()) { + mWindows.Remove(aInnerWindowID); + } + + MOZ_ASSERT(mCountListeners); + --mCountListeners; + + return NS_OK; +} + +NS_IMETHODIMP +WebTransportEventService::HasListenerFor(uint64_t aInnerWindowID, + bool* aResult) { + MOZ_ASSERT(NS_IsMainThread()); + + *aResult = mWindows.Get(aInnerWindowID); + + return NS_OK; +} + +NS_IMETHODIMP +WebTransportEventService::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) { + MOZ_ASSERT(NS_IsMainThread()); + + if (!strcmp(aTopic, "xpcom-shutdown")) { + Shutdown(); + return NS_OK; + } + + if (!strcmp(aTopic, "inner-window-destroyed") && HasListeners()) { + nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject); + NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE); + + uint64_t innerWindowID; + nsresult rv = wrapper->GetData(&innerWindowID); + NS_ENSURE_SUCCESS(rv, rv); + + WindowListener* listener = mWindows.Get(innerWindowID); + if (!listener) { + return NS_OK; + } + + MOZ_ASSERT(mCountListeners >= listener->mListeners.Length()); + mCountListeners -= listener->mListeners.Length(); + mWindows.Remove(innerWindowID); + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +bool WebTransportEventService::HasListeners() const { + return !!mCountListeners; +} + +void WebTransportEventService::Shutdown() { + MOZ_ASSERT(NS_IsMainThread()); + if (gWebTransportEventService) { + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (obs) { + obs->RemoveObserver(gWebTransportEventService, "xpcom-shutdown"); + obs->RemoveObserver(gWebTransportEventService, "inner-window-destroyed"); + } + + mWindows.Clear(); + gWebTransportEventService = nullptr; + } +} + +} // namespace net +} // namespace mozilla diff --git a/netwerk/protocol/webtransport/WebTransportEventService.h b/netwerk/protocol/webtransport/WebTransportEventService.h @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_net_WebTransportEventService_h +#define mozilla_net_WebTransportEventService_h + +#include "mozilla/AlreadyAddRefed.h" +#include "nsIWebTransportEventService.h" +#include "nsCOMPtr.h" +#include "nsTArray.h" +#include "nsIObserver.h" +#include "nsISupportsImpl.h" +#include "nsTHashMap.h" +#include "nsClassHashtable.h" +#include "nsHashKeys.h" + +namespace mozilla { +namespace net { + +class WebTransportEventService final : public nsIWebTransportEventService, + public nsIObserver { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + NS_DECL_NSIWEBTRANSPORTEVENTSERVICE + + static already_AddRefed<WebTransportEventService> GetOrCreate(); + + private: + WebTransportEventService(); + ~WebTransportEventService(); + + bool HasListeners() const; + + using WebTransportEventListeners = + nsTArray<nsCOMPtr<nsIWebTransportEventListener>>; + + struct WindowListener { + WebTransportEventListeners mListeners; + }; + + void Shutdown(); + + nsClassHashtable<nsUint64HashKey, WindowListener> mWindows; + + uint64_t mCountListeners; +}; + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_WebTransportEventService_h diff --git a/netwerk/protocol/webtransport/moz.build b/netwerk/protocol/webtransport/moz.build @@ -9,18 +9,21 @@ with Files("**"): XPIDL_SOURCES += [ "nsIWebTransport.idl", + "nsIWebTransportEventService.idl", "nsIWebTransportStream.idl", ] XPIDL_MODULE = "necko_webtransport" EXPORTS.mozilla.net += [ + "WebTransportEventService.h", "WebTransportHash.h", "WebTransportSessionProxy.h", "WebTransportStreamProxy.h", ] UNIFIED_SOURCES += [ + "WebTransportEventService.cpp", "WebTransportHash.cpp", "WebTransportSessionProxy.cpp", "WebTransportStreamProxy.cpp", diff --git a/netwerk/protocol/webtransport/nsIWebTransportEventService.idl b/netwerk/protocol/webtransport/nsIWebTransportEventService.idl @@ -0,0 +1,24 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +#include "nsISupports.idl" + +[scriptable, uuid(5f34ad48-92ec-4684-ab08-76f6ead9008d)] +interface nsIWebTransportEventListener : nsISupports +{ + // TODO: The functions for this interface are still TBD +}; + +[scriptable, builtinclass, uuid(0907d7d4-351b-4513-a2d9-f6e6467d59ec)] +interface nsIWebTransportEventService : nsISupports +{ + [must_use] void addListener(in unsigned long long aInnerWindowID, + in nsIWebTransportEventListener aListener); + + [must_use] void removeListener(in unsigned long long aInnerWindowID, + in nsIWebTransportEventListener aListener); + + [must_use] boolean hasListenerFor(in unsigned long long aInnerWindowID); +};