зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1790677: Initial WebTransport IPC for creating and closing WebTransport r=webidl,ipc-reviewers,smaug,nika
Differential Revision: https://phabricator.services.mozilla.com/D164124
This commit is contained in:
Родитель
d3c6c33e10
Коммит
faeae8bbf8
|
@ -29,7 +29,7 @@ enum WebTransportCongestionControl {
|
||||||
|
|
||||||
dictionary WebTransportCloseInfo {
|
dictionary WebTransportCloseInfo {
|
||||||
unsigned long closeCode = 0;
|
unsigned long closeCode = 0;
|
||||||
DOMString reason = "";
|
UTF8String reason = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
/* https://w3c.github.io/webtransport/#web-transport-stats */
|
/* https://w3c.github.io/webtransport/#web-transport-stats */
|
||||||
|
@ -62,6 +62,7 @@ dictionary WebTransportDatagramStats {
|
||||||
|
|
||||||
[Exposed=(Window,Worker), SecureContext, Pref="network.webtransport.enabled"]
|
[Exposed=(Window,Worker), SecureContext, Pref="network.webtransport.enabled"]
|
||||||
interface WebTransport {
|
interface WebTransport {
|
||||||
|
[Throws]
|
||||||
constructor(USVString url, optional WebTransportOptions options = {});
|
constructor(USVString url, optional WebTransportOptions options = {});
|
||||||
|
|
||||||
[NewObject]
|
[NewObject]
|
||||||
|
|
|
@ -5,12 +5,22 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "WebTransport.h"
|
#include "WebTransport.h"
|
||||||
|
|
||||||
|
#include "nsUTF8Utils.h"
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
|
#include "mozilla/dom/PWebTransport.h"
|
||||||
|
#include "mozilla/dom/ReadableStream.h"
|
||||||
|
#include "mozilla/dom/WebTransportLog.h"
|
||||||
|
#include "mozilla/ipc/BackgroundChild.h"
|
||||||
|
#include "mozilla/ipc/Endpoint.h"
|
||||||
|
#include "mozilla/ipc/PBackgroundChild.h"
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebTransport, mGlobal)
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebTransport, mGlobal,
|
||||||
|
mIncomingUnidirectionalStreams,
|
||||||
|
mIncomingBidirectionalStreams, mReady)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebTransport)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebTransport)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebTransport)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebTransport)
|
||||||
|
@ -19,6 +29,11 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebTransport)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||||
NS_INTERFACE_MAP_END
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
|
WebTransport::WebTransport(nsIGlobalObject* aGlobal)
|
||||||
|
: mGlobal(aGlobal), mState(WebTransportState::CONNECTING) {
|
||||||
|
LOG(("Creating WebTransport %p", this));
|
||||||
|
}
|
||||||
|
|
||||||
// WebIDL Boilerplate
|
// WebIDL Boilerplate
|
||||||
|
|
||||||
nsIGlobalObject* WebTransport::GetParentObject() const { return mGlobal; }
|
nsIGlobalObject* WebTransport::GetParentObject() const { return mGlobal; }
|
||||||
|
@ -32,9 +47,110 @@ JSObject* WebTransport::WrapObject(JSContext* aCx,
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
already_AddRefed<WebTransport> WebTransport::Constructor(
|
already_AddRefed<WebTransport> WebTransport::Constructor(
|
||||||
const GlobalObject& aGlobal, const nsAString& aUrl,
|
const GlobalObject& aGlobal, const nsAString& aURL,
|
||||||
const WebTransportOptions& aOptions) {
|
const WebTransportOptions& aOptions, ErrorResult& aError) {
|
||||||
return nullptr;
|
LOG(("Creating WebTransport for %s", NS_ConvertUTF16toUTF8(aURL).get()));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||||
|
RefPtr<WebTransport> result = new WebTransport(global);
|
||||||
|
if (!result->Init(aGlobal, aURL, aOptions, aError)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebTransport::Init(const GlobalObject& aGlobal, const nsAString& aURL,
|
||||||
|
const WebTransportOptions& aOptions,
|
||||||
|
ErrorResult& aError) {
|
||||||
|
// Initiate connection with parent
|
||||||
|
using mozilla::ipc::BackgroundChild;
|
||||||
|
using mozilla::ipc::Endpoint;
|
||||||
|
using mozilla::ipc::PBackgroundChild;
|
||||||
|
|
||||||
|
mReady = Promise::Create(mGlobal, aError);
|
||||||
|
if (NS_WARN_IF(aError.Failed())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QueuingStrategy strategy;
|
||||||
|
Optional<JS::Handle<JSObject*>> underlying;
|
||||||
|
mIncomingUnidirectionalStreams =
|
||||||
|
ReadableStream::Constructor(aGlobal, underlying, strategy, aError);
|
||||||
|
if (aError.Failed()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mIncomingBidirectionalStreams =
|
||||||
|
ReadableStream::Constructor(aGlobal, underlying, strategy, aError);
|
||||||
|
if (aError.Failed()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PBackgroundChild* backgroundChild =
|
||||||
|
BackgroundChild::GetOrCreateForCurrentThread();
|
||||||
|
if (NS_WARN_IF(!backgroundChild)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new IPC connection
|
||||||
|
Endpoint<PWebTransportParent> parentEndpoint;
|
||||||
|
Endpoint<PWebTransportChild> childEndpoint;
|
||||||
|
MOZ_ALWAYS_SUCCEEDS(
|
||||||
|
PWebTransport::CreateEndpoints(&parentEndpoint, &childEndpoint));
|
||||||
|
|
||||||
|
RefPtr<WebTransportChild> child = new WebTransportChild();
|
||||||
|
if (!childEndpoint.Bind(child)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mState = WebTransportState::CONNECTING;
|
||||||
|
LOG(("Connecting WebTransport to parent for %s",
|
||||||
|
NS_ConvertUTF16toUTF8(aURL).get()));
|
||||||
|
|
||||||
|
// XXX TODO: Parse string for validity and Throw a SyntaxError if it isn't
|
||||||
|
// XXX and other steps in the constructor requirement (TypeError). Order is
|
||||||
|
// important.
|
||||||
|
// https://w3c.github.io/webtransport/#webtransport-constructor Spec 5.2
|
||||||
|
backgroundChild
|
||||||
|
->SendCreateWebTransportParent(aURL /*, aOptions*/,
|
||||||
|
std::move(parentEndpoint))
|
||||||
|
->Then(
|
||||||
|
GetCurrentSerialEventTarget(), __func__,
|
||||||
|
[self = RefPtr{this}, child](nsresult rv) {
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
self->RejectWaitingConnection(rv);
|
||||||
|
} else {
|
||||||
|
// This will process anything waiting for the connection to
|
||||||
|
// complete;
|
||||||
|
self->ResolveWaitingConnection(child);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[self = RefPtr<WebTransport>(this)](
|
||||||
|
const mozilla::ipc::ResponseRejectReason&) {
|
||||||
|
// This will process anything waiting for the connection to
|
||||||
|
// complete;
|
||||||
|
self->RejectWaitingConnection(NS_ERROR_FAILURE);
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTransport::ResolveWaitingConnection(WebTransportChild* aChild) {
|
||||||
|
LOG(("Resolved Connection %p", this));
|
||||||
|
MOZ_ASSERT(mState == WebTransportState::CONNECTING);
|
||||||
|
mChild = aChild;
|
||||||
|
mState = WebTransportState::CONNECTED;
|
||||||
|
|
||||||
|
mReady->MaybeResolve(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTransport::RejectWaitingConnection(nsresult aRv) {
|
||||||
|
LOG(("Reject Connection %p", this));
|
||||||
|
MOZ_ASSERT(mState == WebTransportState::CONNECTING);
|
||||||
|
mState = WebTransportState::FAILED;
|
||||||
|
LOG(("Rejected connection %x", aRv));
|
||||||
|
|
||||||
|
mReady->MaybeReject(aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<Promise> WebTransport::GetStats(ErrorResult& aError) {
|
already_AddRefed<Promise> WebTransport::GetStats(ErrorResult& aError) {
|
||||||
|
@ -42,15 +158,7 @@ already_AddRefed<Promise> WebTransport::GetStats(ErrorResult& aError) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<Promise> WebTransport::Ready() {
|
already_AddRefed<Promise> WebTransport::Ready() { return do_AddRef(mReady); }
|
||||||
ErrorResult error;
|
|
||||||
RefPtr<Promise> promise = Promise::Create(GetParentObject(), error);
|
|
||||||
if (error.Failed()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
promise->MaybeRejectWithUndefined();
|
|
||||||
return promise.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
WebTransportReliabilityMode WebTransport::Reliability() {
|
WebTransportReliabilityMode WebTransport::Reliability() {
|
||||||
// XXX not implemented
|
// XXX not implemented
|
||||||
|
@ -68,37 +176,70 @@ already_AddRefed<Promise> WebTransport::Closed() {
|
||||||
if (error.Failed()) {
|
if (error.Failed()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
promise->MaybeRejectWithUndefined();
|
promise->MaybeResolve(mState == WebTransportState::CLOSED);
|
||||||
return promise.forget();
|
return promise.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebTransport::Close(const WebTransportCloseInfo& aOptions) {}
|
void WebTransport::Close(const WebTransportCloseInfo& aOptions) {
|
||||||
|
LOG(("Close() called"));
|
||||||
|
if (mState == WebTransportState::CONNECTED ||
|
||||||
|
mState == WebTransportState::CONNECTING) {
|
||||||
|
MOZ_ASSERT(mChild);
|
||||||
|
LOG(("Sending Close"));
|
||||||
|
// "Let reasonString be the maximal code unit prefix of
|
||||||
|
// closeInfo.reason where the length of the UTF-8 encoded prefix
|
||||||
|
// doesn’t exceed 1024."
|
||||||
|
// Take the maximal "code unit prefix" of mReason and limit to 1024 bytes
|
||||||
|
// https://w3c.github.io/webtransport/#webtransport-methods 5.4
|
||||||
|
|
||||||
|
if (aOptions.mReason.Length() > 1024u) {
|
||||||
|
// We want to start looking for the previous code point at one past the
|
||||||
|
// limit, since if a code point ends exactly at the specified length, the
|
||||||
|
// next byte will be the start of a new code point. Note
|
||||||
|
// RewindToPriorUTF8Codepoint doesn't reduce the index if it points to the
|
||||||
|
// start of a code point. We know reason[1024] is accessible since
|
||||||
|
// Length() > 1024
|
||||||
|
mChild->SendClose(
|
||||||
|
aOptions.mCloseCode,
|
||||||
|
Substring(aOptions.mReason, 0,
|
||||||
|
RewindToPriorUTF8Codepoint(aOptions.mReason.get(), 1024u)));
|
||||||
|
} else {
|
||||||
|
mChild->SendClose(aOptions.mCloseCode, aOptions.mReason);
|
||||||
|
}
|
||||||
|
mState = WebTransportState::CLOSED;
|
||||||
|
|
||||||
|
// The other side will call `Close()` for us now, make sure we don't call it
|
||||||
|
// in our destructor.
|
||||||
|
mChild = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<WebTransportDatagramDuplexStream> WebTransport::Datagrams() {
|
already_AddRefed<WebTransportDatagramDuplexStream> WebTransport::Datagrams() {
|
||||||
|
LOG(("Datagrams() called"));
|
||||||
// XXX not implemented
|
// XXX not implemented
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<Promise> WebTransport::CreateBidirectionalStream(
|
already_AddRefed<Promise> WebTransport::CreateBidirectionalStream(
|
||||||
ErrorResult& aError) {
|
ErrorResult& aError) {
|
||||||
|
LOG(("CreateBidirectionalStream() called"));
|
||||||
aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<ReadableStream> WebTransport::IncomingBidirectionalStreams() {
|
already_AddRefed<ReadableStream> WebTransport::IncomingBidirectionalStreams() {
|
||||||
// XXX not implemented
|
return do_AddRef(mIncomingBidirectionalStreams);
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<Promise> WebTransport::CreateUnidirectionalStream(
|
already_AddRefed<Promise> WebTransport::CreateUnidirectionalStream(
|
||||||
ErrorResult& aError) {
|
ErrorResult& aError) {
|
||||||
|
LOG(("CreateUnidirectionalStream() called"));
|
||||||
aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<ReadableStream> WebTransport::IncomingUnidirectionalStreams() {
|
already_AddRefed<ReadableStream> WebTransport::IncomingUnidirectionalStreams() {
|
||||||
// XXX not implemented
|
return do_AddRef(mIncomingUnidirectionalStreams);
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "nsISupports.h"
|
#include "nsISupports.h"
|
||||||
#include "nsWrapperCache.h"
|
#include "nsWrapperCache.h"
|
||||||
#include "mozilla/dom/WebTransportBinding.h"
|
#include "mozilla/dom/WebTransportBinding.h"
|
||||||
|
#include "mozilla/dom/WebTransportChild.h"
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
|
@ -20,11 +21,18 @@ class WritableStream;
|
||||||
|
|
||||||
class WebTransport final : public nsISupports, public nsWrapperCache {
|
class WebTransport final : public nsISupports, public nsWrapperCache {
|
||||||
public:
|
public:
|
||||||
explicit WebTransport(nsIGlobalObject* aGlobal) : mGlobal(aGlobal) {}
|
explicit WebTransport(nsIGlobalObject* aGlobal);
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(WebTransport)
|
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(WebTransport)
|
||||||
|
|
||||||
|
enum class WebTransportState { CONNECTING, CONNECTED, CLOSED, FAILED };
|
||||||
|
|
||||||
|
bool Init(const GlobalObject& aGlobal, const nsAString& aUrl,
|
||||||
|
const WebTransportOptions& aOptions, ErrorResult& aError);
|
||||||
|
void ResolveWaitingConnection(WebTransportChild* aChild);
|
||||||
|
void RejectWaitingConnection(nsresult aRv);
|
||||||
|
|
||||||
// WebIDL Boilerplate
|
// WebIDL Boilerplate
|
||||||
nsIGlobalObject* GetParentObject() const;
|
nsIGlobalObject* GetParentObject() const;
|
||||||
|
|
||||||
|
@ -34,7 +42,7 @@ class WebTransport final : public nsISupports, public nsWrapperCache {
|
||||||
// WebIDL Interface
|
// WebIDL Interface
|
||||||
static already_AddRefed<WebTransport> Constructor(
|
static already_AddRefed<WebTransport> Constructor(
|
||||||
const GlobalObject& aGlobal, const nsAString& aUrl,
|
const GlobalObject& aGlobal, const nsAString& aUrl,
|
||||||
const WebTransportOptions& aOptions);
|
const WebTransportOptions& aOptions, ErrorResult& aRv);
|
||||||
|
|
||||||
already_AddRefed<Promise> GetStats(ErrorResult& aError);
|
already_AddRefed<Promise> GetStats(ErrorResult& aError);
|
||||||
|
|
||||||
|
@ -49,11 +57,25 @@ class WebTransport final : public nsISupports, public nsWrapperCache {
|
||||||
already_AddRefed<Promise> CreateUnidirectionalStream(ErrorResult& aError);
|
already_AddRefed<Promise> CreateUnidirectionalStream(ErrorResult& aError);
|
||||||
already_AddRefed<ReadableStream> IncomingUnidirectionalStreams();
|
already_AddRefed<ReadableStream> IncomingUnidirectionalStreams();
|
||||||
|
|
||||||
|
void Shutdown() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~WebTransport() = default;
|
~WebTransport() {
|
||||||
|
// If this WebTransport was destroyed without being closed properly, make
|
||||||
|
// sure to clean up the channel.
|
||||||
|
if (mChild) {
|
||||||
|
mChild->Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||||
// RefPtr<WebTransportChannel> mChannel;
|
RefPtr<WebTransportChild> mChild;
|
||||||
|
|
||||||
|
// These are created in the constructor
|
||||||
|
RefPtr<ReadableStream> mIncomingUnidirectionalStreams;
|
||||||
|
RefPtr<ReadableStream> mIncomingBidirectionalStreams;
|
||||||
|
RefPtr<Promise> mReady;
|
||||||
|
WebTransportState mState;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|
|
@ -21,3 +21,5 @@ UNIFIED_SOURCES += [
|
||||||
]
|
]
|
||||||
|
|
||||||
FINAL_LIBRARY = "xul"
|
FINAL_LIBRARY = "xul"
|
||||||
|
|
||||||
|
include("/ipc/chromium/chromium-config.mozbuild")
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/* -*- 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 DOM_WEBTRANSPORT_WEBTRANSPORTCHILD_H_
|
||||||
|
#define DOM_WEBTRANSPORT_WEBTRANSPORTCHILD_H_
|
||||||
|
|
||||||
|
#include "mozilla/dom/PWebTransportChild.h"
|
||||||
|
#include "nsISupportsImpl.h"
|
||||||
|
|
||||||
|
namespace mozilla::dom {
|
||||||
|
|
||||||
|
class WebTransportChild : public PWebTransportChild {
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_REFCOUNTING(WebTransportChild)
|
||||||
|
|
||||||
|
virtual void CloseAll() {
|
||||||
|
// XXX need impl
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Shutdown() {
|
||||||
|
if (!CanSend()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
::mozilla::ipc::IPCResult RecvCloseAll(CloseAllResolver&& aResolver) {
|
||||||
|
CloseAll();
|
||||||
|
aResolver(NS_OK);
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~WebTransportChild() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla::dom
|
||||||
|
|
||||||
|
#endif // DOM_WEBTRANSPORT_WEBTRANSPORTCHILD_H_
|
|
@ -0,0 +1,13 @@
|
||||||
|
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
EXPORTS.mozilla.dom += [
|
||||||
|
"WebTransportChild.h",
|
||||||
|
]
|
||||||
|
|
||||||
|
FINAL_LIBRARY = "xul"
|
||||||
|
|
||||||
|
include("/ipc/chromium/chromium-config.mozbuild")
|
|
@ -6,4 +6,8 @@
|
||||||
|
|
||||||
DIRS += [
|
DIRS += [
|
||||||
"api",
|
"api",
|
||||||
|
"child",
|
||||||
|
"parent",
|
||||||
|
"shared",
|
||||||
|
"test",
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/* -*- 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 "WebTransportParent.h"
|
||||||
|
|
||||||
|
#include "mozilla/StaticPrefs_network.h"
|
||||||
|
#include "mozilla/dom/WebTransportLog.h"
|
||||||
|
#include "mozilla/ipc/BackgroundParent.h"
|
||||||
|
|
||||||
|
using IPCResult = mozilla::ipc::IPCResult;
|
||||||
|
|
||||||
|
namespace mozilla::dom {
|
||||||
|
|
||||||
|
WebTransportParent::~WebTransportParent() {
|
||||||
|
LOG(("Destroying WebTransportParent %p", this));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebTransportParent::Init(
|
||||||
|
const nsAString& aURL,
|
||||||
|
// WebTransportOptions aOptions,
|
||||||
|
Endpoint<PWebTransportParent>&& aParentEndpoint,
|
||||||
|
std::function<void(const nsresult&)>&& aResolver) {
|
||||||
|
LOG(("Created WebTransportParent %p %s", this,
|
||||||
|
NS_ConvertUTF16toUTF8(aURL).get()));
|
||||||
|
|
||||||
|
if (!StaticPrefs::network_webtransport_enabled()) {
|
||||||
|
aResolver(NS_ERROR_DOM_NOT_ALLOWED_ERR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aParentEndpoint.IsValid()) {
|
||||||
|
aResolver(NS_ERROR_INVALID_ARG);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aParentEndpoint.Bind(this)) {
|
||||||
|
aResolver(NS_ERROR_FAILURE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// XXX Send connection to the server
|
||||||
|
aResolver(NS_OK);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTransportParent::ActorDestroy(ActorDestroyReason aWhy) {
|
||||||
|
LOG(("ActorDestroy WebTransportParent %d", aWhy));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We may not receive this response if the child side is destroyed without
|
||||||
|
// `Close` or `Shutdown` being explicitly called.
|
||||||
|
mozilla::ipc::IPCResult WebTransportParent::RecvClose(
|
||||||
|
const uint32_t& aCode, const nsACString& aReason) {
|
||||||
|
LOG(("Close received, code = %u, reason = %s", aCode,
|
||||||
|
PromiseFlatCString(aReason).get()));
|
||||||
|
// XXX shut down streams cleanly
|
||||||
|
Close();
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla::dom
|
|
@ -0,0 +1,40 @@
|
||||||
|
/* -*- 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 DOM_WEBTRANSPORT_PARENT_WEBTRANSPORTPARENT_H_
|
||||||
|
#define DOM_WEBTRANSPORT_PARENT_WEBTRANSPORTPARENT_H_
|
||||||
|
|
||||||
|
#include "ErrorList.h"
|
||||||
|
#include "mozilla/dom/FlippedOnce.h"
|
||||||
|
#include "mozilla/dom/PWebTransportParent.h"
|
||||||
|
#include "mozilla/ipc/Endpoint.h"
|
||||||
|
#include "nsISupports.h"
|
||||||
|
|
||||||
|
namespace mozilla::dom {
|
||||||
|
|
||||||
|
class WebTransportParent : public PWebTransportParent {
|
||||||
|
public:
|
||||||
|
WebTransportParent() = default;
|
||||||
|
|
||||||
|
// XXX Threadsafe??
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebTransportParent, override)
|
||||||
|
|
||||||
|
bool Init(const nsAString& aURL, // WebTransportOptions aOptions,
|
||||||
|
Endpoint<PWebTransportParent>&& aParentEndpoint,
|
||||||
|
std::function<void(const nsresult&)>&& aResolver);
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult RecvClose(const uint32_t& aCode,
|
||||||
|
const nsACString& aReason);
|
||||||
|
|
||||||
|
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~WebTransportParent();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla::dom
|
||||||
|
|
||||||
|
#endif // DOM_WEBTRANSPORT_PARENT_WEBTRANSPORTPARENT_H_
|
|
@ -0,0 +1,17 @@
|
||||||
|
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
EXPORTS.mozilla.dom += [
|
||||||
|
"WebTransportParent.h",
|
||||||
|
]
|
||||||
|
|
||||||
|
UNIFIED_SOURCES += [
|
||||||
|
"WebTransportParent.cpp",
|
||||||
|
]
|
||||||
|
|
||||||
|
FINAL_LIBRARY = "xul"
|
||||||
|
|
||||||
|
include("/ipc/chromium/chromium-config.mozbuild")
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
using struct mozilla::void_t from "mozilla/ipc/IPCCore.h";
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
async protocol PWebTransport
|
||||||
|
{
|
||||||
|
parent:
|
||||||
|
/**
|
||||||
|
* TODO: documentation
|
||||||
|
*/
|
||||||
|
async Close(uint32_t code, nsCString reason);
|
||||||
|
|
||||||
|
child:
|
||||||
|
|
||||||
|
async CloseAll()
|
||||||
|
returns(nsresult rv);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
/* -*- 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 "WebTransportLog.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
LazyLogModule gWebTransportLog("WebTransport");
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* -*- 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 DOM_WEBTRANSPORT_SHARED_WEBTRANSPORTLOG_H_
|
||||||
|
#define DOM_WEBTRANSPORT_SHARED_WEBTRANSPORTLOG_H_
|
||||||
|
|
||||||
|
#include "mozilla/Logging.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
extern LazyLogModule gWebTransportLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LOG(args) \
|
||||||
|
MOZ_LOG(mozilla::gWebTransportLog, mozilla::LogLevel::Debug, args)
|
||||||
|
|
||||||
|
#define LOG_VERBOSE(args) \
|
||||||
|
MOZ_LOG(mozilla::gWebTransportLog, mozilla::LogLevel::Verbose, args)
|
||||||
|
|
||||||
|
#define LOG_ENABLED() \
|
||||||
|
MOZ_LOG_TEST(mozilla::gWebTransportLog, mozilla::LogLevel::Debug)
|
||||||
|
|
||||||
|
#endif // DOM_WEBTRANSPORT_SHARED_WEBTRANSPORTLOG_H
|
|
@ -0,0 +1,21 @@
|
||||||
|
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
EXPORTS.mozilla.dom += [
|
||||||
|
"WebTransportLog.h",
|
||||||
|
]
|
||||||
|
|
||||||
|
UNIFIED_SOURCES += [
|
||||||
|
"WebTransportLog.cpp",
|
||||||
|
]
|
||||||
|
|
||||||
|
FINAL_LIBRARY = "xul"
|
||||||
|
|
||||||
|
IPDL_SOURCES += [
|
||||||
|
"PWebTransport.ipdl",
|
||||||
|
]
|
||||||
|
|
||||||
|
include("/ipc/chromium/chromium-config.mozbuild")
|
|
@ -0,0 +1,9 @@
|
||||||
|
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
TEST_DIRS += [
|
||||||
|
"xpcshell",
|
||||||
|
]
|
|
@ -0,0 +1,9 @@
|
||||||
|
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
XPCSHELL_TESTS_MANIFESTS += [
|
||||||
|
"xpcshell.ini",
|
||||||
|
]
|
|
@ -0,0 +1,64 @@
|
||||||
|
//
|
||||||
|
// Simple WebTransport test
|
||||||
|
//
|
||||||
|
// keep eslint happy until it knows about WebTransport
|
||||||
|
/* global WebTransport:false */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var h3Port;
|
||||||
|
var host;
|
||||||
|
|
||||||
|
registerCleanupFunction(async () => {
|
||||||
|
Services.prefs.clearUserPref("network.dns.localDomains");
|
||||||
|
});
|
||||||
|
|
||||||
|
var { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
||||||
|
|
||||||
|
function readFile(file) {
|
||||||
|
let fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
|
||||||
|
Ci.nsIFileInputStream
|
||||||
|
);
|
||||||
|
fstream.init(file, -1, 0, 0);
|
||||||
|
let data = NetUtil.readInputStreamToString(fstream, fstream.available());
|
||||||
|
fstream.close();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCertFromFile(certdb, filename, trustString) {
|
||||||
|
let certFile = do_get_file(filename, false);
|
||||||
|
let pem = readFile(certFile)
|
||||||
|
.replace(/-----BEGIN CERTIFICATE-----/, "")
|
||||||
|
.replace(/-----END CERTIFICATE-----/, "")
|
||||||
|
.replace(/[\r\n]/g, "");
|
||||||
|
certdb.addCertFromBase64(pem, trustString);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(async function setup() {
|
||||||
|
Services.prefs.setCharPref("network.dns.localDomains", "foo.example.com");
|
||||||
|
|
||||||
|
h3Port = Services.env.get("MOZHTTP3_PORT");
|
||||||
|
Assert.notEqual(h3Port, null);
|
||||||
|
Assert.notEqual(h3Port, "");
|
||||||
|
host = "foo.example.com:" + h3Port;
|
||||||
|
do_get_profile();
|
||||||
|
|
||||||
|
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
|
||||||
|
Ci.nsIX509CertDB
|
||||||
|
);
|
||||||
|
// `../unit/` so that unit_ipc tests can use as well
|
||||||
|
addCertFromFile(
|
||||||
|
certdb,
|
||||||
|
"../../../../netwerk/test/unit/http2-ca.pem",
|
||||||
|
"CTu,u,u"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_webtransport_create() {
|
||||||
|
Services.prefs.setBoolPref("network.webtransport.enabled", true);
|
||||||
|
|
||||||
|
const wt = new WebTransport("https://" + host + "/success");
|
||||||
|
await wt.ready;
|
||||||
|
|
||||||
|
wt.close();
|
||||||
|
});
|
|
@ -0,0 +1,7 @@
|
||||||
|
# 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]
|
||||||
|
|
||||||
|
[test_close.js]
|
|
@ -48,6 +48,7 @@
|
||||||
#include "mozilla/dom/StorageIPC.h"
|
#include "mozilla/dom/StorageIPC.h"
|
||||||
#include "mozilla/dom/TemporaryIPCBlobParent.h"
|
#include "mozilla/dom/TemporaryIPCBlobParent.h"
|
||||||
#include "mozilla/dom/WebAuthnTransactionParent.h"
|
#include "mozilla/dom/WebAuthnTransactionParent.h"
|
||||||
|
#include "mozilla/dom/WebTransportParent.h"
|
||||||
#include "mozilla/dom/cache/ActorUtils.h"
|
#include "mozilla/dom/cache/ActorUtils.h"
|
||||||
#include "mozilla/dom/indexedDB/ActorsParent.h"
|
#include "mozilla/dom/indexedDB/ActorsParent.h"
|
||||||
#include "mozilla/dom/locks/LockManagerParent.h"
|
#include "mozilla/dom/locks/LockManagerParent.h"
|
||||||
|
@ -502,6 +503,23 @@ mozilla::ipc::IPCResult BackgroundParentImpl::RecvCreateFileSystemManagerParent(
|
||||||
aPrincipalInfo, std::move(aParentEndpoint), std::move(aResolver));
|
aPrincipalInfo, std::move(aParentEndpoint), std::move(aResolver));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult BackgroundParentImpl::RecvCreateWebTransportParent(
|
||||||
|
const nsAString& aURL,
|
||||||
|
// WebTransportOptions aOptions,
|
||||||
|
Endpoint<PWebTransportParent>&& aParentEndpoint,
|
||||||
|
CreateWebTransportParentResolver&& aResolver) {
|
||||||
|
AssertIsInMainProcess();
|
||||||
|
AssertIsOnBackgroundThread();
|
||||||
|
|
||||||
|
RefPtr<mozilla::dom::WebTransportParent> webt =
|
||||||
|
new mozilla::dom::WebTransportParent();
|
||||||
|
if (!webt->Init(aURL, /*aOptions, */ std::move(aParentEndpoint),
|
||||||
|
std::move(aResolver))) {
|
||||||
|
webt->Close();
|
||||||
|
}
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<PIdleSchedulerParent>
|
already_AddRefed<PIdleSchedulerParent>
|
||||||
BackgroundParentImpl::AllocPIdleSchedulerParent() {
|
BackgroundParentImpl::AllocPIdleSchedulerParent() {
|
||||||
AssertIsOnBackgroundThread();
|
AssertIsOnBackgroundThread();
|
||||||
|
|
|
@ -137,6 +137,12 @@ class BackgroundParentImpl : public PBackgroundParent {
|
||||||
Endpoint<mozilla::dom::PFileSystemManagerParent>&& aParentEndpoint,
|
Endpoint<mozilla::dom::PFileSystemManagerParent>&& aParentEndpoint,
|
||||||
CreateFileSystemManagerParentResolver&& aResolver) override;
|
CreateFileSystemManagerParentResolver&& aResolver) override;
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult RecvCreateWebTransportParent(
|
||||||
|
const nsAString& aURL,
|
||||||
|
// WebTransportOptions aOptions,
|
||||||
|
Endpoint<PWebTransportParent>&& aParentEndpoint,
|
||||||
|
CreateWebTransportParentResolver&& aResolver) override;
|
||||||
|
|
||||||
already_AddRefed<PIdleSchedulerParent> AllocPIdleSchedulerParent() override;
|
already_AddRefed<PIdleSchedulerParent> AllocPIdleSchedulerParent() override;
|
||||||
|
|
||||||
PTemporaryIPCBlobParent* AllocPTemporaryIPCBlobParent() override;
|
PTemporaryIPCBlobParent* AllocPTemporaryIPCBlobParent() override;
|
||||||
|
|
|
@ -52,6 +52,7 @@ include protocol PVerifySSLServerCert;
|
||||||
include protocol PVsync;
|
include protocol PVsync;
|
||||||
include protocol PRemoteDecoderManager;
|
include protocol PRemoteDecoderManager;
|
||||||
include protocol PWebSocketConnection;
|
include protocol PWebSocketConnection;
|
||||||
|
include protocol PWebTransport;
|
||||||
|
|
||||||
include DOMTypes;
|
include DOMTypes;
|
||||||
include IPCBlob;
|
include IPCBlob;
|
||||||
|
@ -197,6 +198,15 @@ parent:
|
||||||
Endpoint<PFileSystemManagerParent> aParentEndpoint)
|
Endpoint<PFileSystemManagerParent> aParentEndpoint)
|
||||||
returns(nsresult rv);
|
returns(nsresult rv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish the setup of a new PWebTransport top level protocol.
|
||||||
|
*/
|
||||||
|
async CreateWebTransportParent(
|
||||||
|
nsString aURL,
|
||||||
|
/* WebTransportOptions aOptions, */
|
||||||
|
Endpoint<PWebTransportParent> aParentEndpoint)
|
||||||
|
returns(nsresult rv);
|
||||||
|
|
||||||
async PVsync();
|
async PVsync();
|
||||||
|
|
||||||
async PCameras();
|
async PCameras();
|
||||||
|
|
|
@ -63,7 +63,9 @@ promise_test(async t => {
|
||||||
const close_info = await wt.closed;
|
const close_info = await wt.closed;
|
||||||
|
|
||||||
assert_equals(close_info.closeCode, 11, 'code');
|
assert_equals(close_info.closeCode, 11, 'code');
|
||||||
assert_equals(close_info.reason, reason, 'reason');
|
// This should be truncated to 1023 bytes!
|
||||||
|
const reason_truncated = 'あいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあ';
|
||||||
|
assert_equals(close_info.reason, reason_truncated, 'reason');
|
||||||
|
|
||||||
await wait(10);
|
await wait(10);
|
||||||
const data = await query(id);
|
const data = await query(id);
|
||||||
|
|
|
@ -92,4 +92,4 @@ async function readInto(reader, buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче