Backed out 2 changesets (bug 1830096) for xpc failures on test_webtransport_simple.js. CLOSED TREE

Backed out changeset 54cc048fd39a (bug 1830096)
Backed out changeset 7337707e8b32 (bug 1830096)
This commit is contained in:
Narcis Beleuzu 2023-04-27 18:31:49 +03:00
parent f1a92cac23
commit 82030e5f73
6 changed files with 66 additions and 153 deletions

View file

@ -333,8 +333,6 @@ void WebTransport::Init(const GlobalObject& aGlobal, const nsAString& aURL,
NS_ConvertUTF16toUTF8(aURL).get()));
// https://w3c.github.io/webtransport/#webtransport-constructor Spec 5.2
mChild = child;
mDatagrams->SetChild(child);
backgroundChild
->SendCreateWebTransportParent(aURL, principal, ipcClientInfo, dedicated,
requireUnreliable,
@ -342,9 +340,9 @@ void WebTransport::Init(const GlobalObject& aGlobal, const nsAString& aURL,
// XXX serverCertHashes,
std::move(parentEndpoint))
->Then(GetCurrentSerialEventTarget(), __func__,
[self = RefPtr{this}](
PBackgroundChild::CreateWebTransportParentPromise::
ResolveOrRejectValue&& aResult) {
[self = RefPtr{this},
child](PBackgroundChild::CreateWebTransportParentPromise::
ResolveOrRejectValue&& aResult) {
// aResult is a std::tuple<nsresult, uint8_t>
// TODO: is there a better/more-spec-compliant error in the
// reject case? Which begs the question, why would we get a
@ -355,20 +353,21 @@ void WebTransport::Init(const GlobalObject& aGlobal, const nsAString& aURL,
LOG(("isreject: %d nsresult 0x%x", aResult.IsReject(),
(uint32_t)rv));
if (NS_FAILED(rv)) {
self->RejectWaitingConnection(rv);
self->RejectWaitingConnection(rv, child);
} else {
// This will process anything waiting for the connection to
// complete;
self->ResolveWaitingConnection(
static_cast<WebTransportReliabilityMode>(
std::get<1>(aResult.ResolveValue())));
std::get<1>(aResult.ResolveValue())),
child);
}
});
}
void WebTransport::ResolveWaitingConnection(
WebTransportReliabilityMode aReliability) {
WebTransportReliabilityMode aReliability, WebTransportChild* aChild) {
LOG(("Resolved Connection %p, reliability = %u", this,
(unsigned)aReliability));
// https://w3c.github.io/webtransport/#webtransport-constructor
@ -381,6 +380,8 @@ void WebTransport::ResolveWaitingConnection(
return;
}
mChild = aChild;
mDatagrams->SetChild(aChild);
// Step 17.2: Set transport.[[State]] to "connected".
mState = WebTransportState::CONNECTED;
// Step 17.3: Set transport.[[Session]] to session.
@ -391,7 +392,8 @@ void WebTransport::ResolveWaitingConnection(
mReady->MaybeResolveWithUndefined();
}
void WebTransport::RejectWaitingConnection(nsresult aRv) {
void WebTransport::RejectWaitingConnection(nsresult aRv,
WebTransportChild* aChild) {
LOG(("Rejected connection %p %x", this, (uint32_t)aRv));
// https://w3c.github.io/webtransport/#initialize-webtransport-over-http
@ -406,8 +408,7 @@ void WebTransport::RejectWaitingConnection(nsresult aRv) {
// these steps.
if (mState == WebTransportState::CLOSED ||
mState == WebTransportState::FAILED) {
mChild->Shutdown(true);
mChild = nullptr;
aChild->Shutdown(true);
// Cleanup should have been called, which means Ready has been
// rejected and pulls resolved
return;
@ -420,8 +421,8 @@ void WebTransport::RejectWaitingConnection(nsresult aRv) {
// Step 14.3: Cleanup transport with error.
Cleanup(error, nullptr, IgnoreErrors());
mChild->Shutdown(true);
mChild = nullptr;
// We never set mChild, but we need to prepare it to die
aChild->Shutdown(true);
}
bool WebTransport::ParseURL(const nsAString& aURL) const {
@ -513,8 +514,7 @@ void WebTransport::Close(const WebTransportCloseInfo& aOptions,
// Step 3.2: Cleanup transport with error.
Cleanup(error, nullptr, aRv);
// Step 3.3: Abort these steps.
mChild->Shutdown(true);
mChild = nullptr;
MOZ_ASSERT(!mChild);
return;
}
LOG(("Sending Close"));
@ -596,10 +596,6 @@ already_AddRefed<Promise> WebTransport::CreateBidirectionalStream(
LOG(("CreateBidirectionalStream response"));
// Step 5.2.1: If transport.[[State]] is "closed" or "failed",
// reject p with an InvalidStateError and abort these steps.
if (BidirectionalStreamResponse::Tnsresult == aPipes.type()) {
promise->MaybeReject(aPipes.get_nsresult());
return;
}
if (self->mState == WebTransportState::CLOSED ||
self->mState == WebTransportState::FAILED) {
promise->MaybeRejectWithInvalidStateError(

View file

@ -64,8 +64,9 @@ class WebTransport final : public nsISupports, public nsWrapperCache {
const nsAString& aUrl,
const WebTransportOptions& aOptions,
ErrorResult& aError);
void ResolveWaitingConnection(WebTransportReliabilityMode aReliability);
void RejectWaitingConnection(nsresult aRv);
void ResolveWaitingConnection(WebTransportReliabilityMode aReliability,
WebTransportChild* aChild);
void RejectWaitingConnection(nsresult aRv, WebTransportChild* aChild);
bool ParseURL(const nsAString& aURL) const;
// this calls CloseNative(), which doesn't actually run script. See bug
// 1810942

View file

@ -277,7 +277,6 @@ JS_HAZ_CAN_RUN_SCRIPT NS_IMETHODIMP ReceiveStream::OnError(uint8_t aError) {
nsresult rv = aError == nsIWebTransport::INVALID_STATE_ERROR
? NS_ERROR_DOM_INVALID_STATE_ERR
: NS_ERROR_FAILURE;
LOG(("CreateStream OnError: %u", aError));
if (mUniResolver) {
mUniResolver(nullptr);
} else if (mBiResolver) {

View file

@ -317,67 +317,18 @@ class WebTransportStreamCallbackWrapper final {
};
void WebTransportSessionProxy::CreateStreamInternal(
nsIWebTransportStreamCallback* callback, bool aBidi) {
mMutex.AssertCurrentThreadOwns();
LOG(
("WebTransportSessionProxy::CreateStreamInternal %p "
"mState=%d, bidi=%d",
this, mState, aBidi));
switch (mState) {
case WebTransportSessionProxyState::INIT:
case WebTransportSessionProxyState::NEGOTIATING:
case WebTransportSessionProxyState::NEGOTIATING_SUCCEEDED:
case WebTransportSessionProxyState::ACTIVE: {
RefPtr<WebTransportStreamCallbackWrapper> wrapper =
new WebTransportStreamCallbackWrapper(callback, aBidi);
if (mState == WebTransportSessionProxyState::ACTIVE &&
mWebTransportSession) {
DoCreateStream(wrapper, mWebTransportSession, aBidi);
} else {
LOG(
("WebTransportSessionProxy::CreateStreamInternal %p "
" queue create stream event",
this));
auto task = [self = RefPtr{this}, wrapper{std::move(wrapper)},
bidi(aBidi)](nsresult aStatus) {
if (NS_FAILED(aStatus)) {
wrapper->CallOnError(aStatus);
return;
}
self->DoCreateStream(wrapper, nullptr, bidi);
};
mPendingCreateStreamEvents.AppendElement(std::move(task));
}
} break;
case WebTransportSessionProxyState::SESSION_CLOSE_PENDING:
case WebTransportSessionProxyState::CLOSE_CALLBACK_PENDING:
case WebTransportSessionProxyState::DONE: {
nsCOMPtr<nsIWebTransportStreamCallback> cb(callback);
NS_DispatchToCurrentThread(NS_NewRunnableFunction(
"WebTransportSessionProxy::CreateOutgoingUnidirectionalStream",
[cb{std::move(cb)}]() {
cb->OnError(nsIWebTransport::INVALID_STATE_ERROR);
}));
} break;
}
}
void WebTransportSessionProxy::DoCreateStream(
WebTransportStreamCallbackWrapper* aCallback,
Http3WebTransportSession* aSession, bool aBidi) {
WebTransportStreamCallbackWrapper* aCallback, bool aBidi) {
if (!OnSocketThread()) {
RefPtr<WebTransportSessionProxy> self(this);
RefPtr<WebTransportStreamCallbackWrapper> wrapper(aCallback);
Unused << gSocketTransportService->Dispatch(NS_NewRunnableFunction(
"WebTransportSessionProxy::DoCreateStream",
"WebTransportSessionProxy::CreateStreamInternal",
[self{std::move(self)}, wrapper{std::move(wrapper)}, bidi(aBidi)]() {
self->DoCreateStream(wrapper, nullptr, bidi);
self->CreateStreamInternal(wrapper, bidi);
}));
return;
}
LOG(("WebTransportSessionProxy::DoCreateStream %p bidi=%d", this, aBidi));
RefPtr<WebTransportStreamCallbackWrapper> wrapper(aCallback);
auto callback =
[wrapper{std::move(wrapper)}](
@ -393,8 +344,8 @@ void WebTransportSessionProxy::DoCreateStream(
wrapper->CallOnStreamReady(streamProxy);
};
RefPtr<Http3WebTransportSession> session = aSession;
if (!aSession) {
RefPtr<Http3WebTransportSession> session;
{
MutexAutoLock lock(mMutex);
session = mWebTransportSession;
}
@ -419,8 +370,23 @@ WebTransportSessionProxy::CreateOutgoingUnidirectionalStream(
return NS_ERROR_INVALID_ARG;
}
MutexAutoLock lock(mMutex);
CreateStreamInternal(callback, false);
{
MutexAutoLock lock(mMutex);
if (mState != WebTransportSessionProxyState::ACTIVE ||
!mWebTransportSession) {
nsCOMPtr<nsIWebTransportStreamCallback> cb(callback);
NS_DispatchToCurrentThread(NS_NewRunnableFunction(
"WebTransportSessionProxy::CreateOutgoingUnidirectionalStream",
[cb{std::move(cb)}]() {
cb->OnError(nsIWebTransport::INVALID_STATE_ERROR);
}));
return NS_OK;
}
}
RefPtr<WebTransportStreamCallbackWrapper> wrapper =
new WebTransportStreamCallbackWrapper(callback, false);
CreateStreamInternal(wrapper, false);
return NS_OK;
}
@ -431,8 +397,23 @@ WebTransportSessionProxy::CreateOutgoingBidirectionalStream(
return NS_ERROR_INVALID_ARG;
}
MutexAutoLock lock(mMutex);
CreateStreamInternal(callback, true);
{
MutexAutoLock lock(mMutex);
if (mState != WebTransportSessionProxyState::ACTIVE ||
!mWebTransportSession) {
nsCOMPtr<nsIWebTransportStreamCallback> cb(callback);
NS_DispatchToCurrentThread(NS_NewRunnableFunction(
"WebTransportSessionProxy::CreateOutgoingBidirectionalStream",
[cb{std::move(cb)}]() {
cb->OnError(nsIWebTransport::INVALID_STATE_ERROR);
}));
return NS_OK;
}
}
RefPtr<WebTransportStreamCallbackWrapper> wrapper =
new WebTransportStreamCallbackWrapper(callback, true);
CreateStreamInternal(wrapper, true);
return NS_OK;
}
@ -580,8 +561,6 @@ WebTransportSessionProxy::OnStopRequest(nsIRequest* aRequest,
uint32_t closeStatus = 0;
uint64_t sessionId;
bool succeeded = false;
nsTArray<std::function<void()>> pendingEvents;
nsTArray<std::function<void(nsresult)>> pendingCreateStreamEvents;
{
MutexAutoLock lock(mMutex);
switch (mState) {
@ -618,25 +597,16 @@ WebTransportSessionProxy::OnStopRequest(nsIRequest* aRequest,
case WebTransportSessionProxyState::DONE:
break;
}
pendingEvents = std::move(mPendingEvents);
pendingCreateStreamEvents = std::move(mPendingCreateStreamEvents);
mStopRequestCalled = true;
}
if (!pendingCreateStreamEvents.IsEmpty()) {
Unused << gSocketTransportService->Dispatch(NS_NewRunnableFunction(
"WebTransportSessionProxy::DispatchPendingCreateStreamEvents",
[pendingCreateStreamEvents = std::move(pendingCreateStreamEvents),
status(aStatus)]() {
for (const auto& event : pendingCreateStreamEvents) {
event(status);
}
}));
}
if (listener) {
if (succeeded) {
listener->OnSessionReady(sessionId);
nsTArray<std::function<void()>> pendingEvents;
{
MutexAutoLock lock(mMutex);
pendingEvents = std::move(mPendingEvents);
mStopRequestCalled = true;
}
if (!pendingEvents.IsEmpty()) {
Unused << gSocketTransportService->Dispatch(NS_NewRunnableFunction(
"WebTransportSessionProxy::DispatchPendingEvents",

View file

@ -158,10 +158,8 @@ class WebTransportSessionProxy final : public nsIWebTransport,
WebTransportSessionProxyState mState MOZ_GUARDED_BY(mMutex) =
WebTransportSessionProxyState::INIT;
void ChangeState(WebTransportSessionProxyState newState);
void CreateStreamInternal(nsIWebTransportStreamCallback* callback,
void CreateStreamInternal(WebTransportStreamCallbackWrapper* aCallback,
bool aBidi);
void DoCreateStream(WebTransportStreamCallbackWrapper* aCallback,
Http3WebTransportSession* aSession, bool aBidi);
void SendDatagramInternal(const RefPtr<Http3WebTransportSession>& aSession,
nsTArray<uint8_t>&& aData, uint64_t aTrackingId);
void NotifyDatagramReceived(nsTArray<uint8_t>&& aData);
@ -182,8 +180,6 @@ class WebTransportSessionProxy final : public nsIWebTransport,
// This is used to store events happened before OnSessionReady.
// Note that these events will be dispatched to the socket thread.
nsTArray<std::function<void()>> mPendingEvents MOZ_GUARDED_BY(mMutex);
nsTArray<std::function<void(nsresult)>> mPendingCreateStreamEvents
MOZ_GUARDED_BY(mMutex);
nsCOMPtr<nsIEventTarget> mTarget MOZ_GUARDED_BY(mMutex);
};

View file

@ -21,27 +21,7 @@ promise_test(async t => {
// Check that the message from the readable end matches the writable end.
assert_equals(reply, 'Hello World');
}, 'WebTransport client should be able to create and handle a bidirectional stream');
promise_test(async t => {
// Establish a WebTransport session.
const wt = new WebTransport(webtransport_url('echo.py'));
// Create a bidirectional stream.
const bidi_stream = await wt.createBidirectionalStream();
// Write a message to the writable end, and close it.
const writer = bidi_stream.writable.getWriter();
const encoder = new TextEncoder();
await writer.write(encoder.encode('Hello World'));
await writer.close();
// Read the data on the readable end.
const reply = await read_stream_as_string(bidi_stream.readable);
// Check that the message from the readable end matches the writable end.
assert_equals(reply, 'Hello World');
}, 'WebTransport client should be able to create and handle a bidirectional stream without waiting for ready');
}, 'WebTransport server should be able to create and handle a bidirectional stream');
promise_test(async t => {
// Establish a WebTransport session.
@ -96,36 +76,7 @@ promise_test(async t => {
// Make sure the message on the writable and readable ends of the streams
// match.
assert_equals(reply, 'Hello World');
}, 'WebTransport client should be able to create, accept, and handle a unidirectional stream');
promise_test(async t => {
// Establish a WebTransport session.
const wt = new WebTransport(webtransport_url('echo.py'));
// Create a unidirectional stream.
const writable = await wt.createUnidirectionalStream();
// Write a message to the writable end, and close it.
const encoder = new TextEncoderStream();
encoder.readable.pipeTo(writable);
const writer = encoder.writable.getWriter();
await writer.write('Hello World');
await writer.close();
// The echo handler creates a new unidirectional stream to echo back data from
// the server to client. Accept the unidirectional stream.
const readable = wt.incomingUnidirectionalStreams;
const stream_reader = readable.getReader();
const { value: recv_stream } = await stream_reader.read();
stream_reader.releaseLock();
// Read the data on the readable end.
const reply = await read_stream_as_string(recv_stream);
// Make sure the message on the writable and readable ends of the streams
// match.
assert_equals(reply, 'Hello World');
}, 'WebTransport client should be able to create, accept, and handle a unidirectional stream without waiting for ready');
}, 'WebTransport server should be able to create, accept, and handle a unidirectional stream');
promise_test(async t => {
// Establish a WebTransport session.