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
This commit is contained in:
Hubert Boma Manilla authored and [email protected] committed 2025-11-10 12:15:21 +00:00
1 parent adb38904a5
commit 1928932c32
8 files changed
+304

No files matched your search

+14
View File
@@ -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"]
+4
View File
@@ -7,3 +7,7 @@
TEST_DIRS += [
"xpcshell",
]
MOCHITEST_CHROME_MANIFESTS += [
"chrome.toml",
]
@@ -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>
+8
View File
@@ -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'):
@@ -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
@@ -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
+3
View File
@@ -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",
@@ -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);
};