mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1551589
: readyState fixes r=ng
Depends on D31085 Differential Revision: https://phabricator.services.mozilla.com/D31123 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
748cc8584f
commit
2d6cf50175
@ -397,12 +397,6 @@ nsresult nsDOMDataChannel::NotBuffered(nsISupports* aContext) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsDOMDataChannel::AppReady() {
|
||||
if (!mSentClose) { // may not be possible, simpler to just test anyways
|
||||
mDataChannel->AppReady();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Methods that keep alive the DataChannel object when:
|
||||
// 1. the object has registered event listeners that can be triggered
|
||||
@ -421,8 +415,7 @@ void nsDOMDataChannel::UpdateMustKeepAlive() {
|
||||
uint16_t readyState = mDataChannel->GetReadyState();
|
||||
|
||||
switch (readyState) {
|
||||
case DataChannel::CONNECTING:
|
||||
case DataChannel::WAITING_TO_OPEN: {
|
||||
case DataChannel::CONNECTING: {
|
||||
if (mListenerManager &&
|
||||
(mListenerManager->HasListenersFor(nsGkAtoms::onopen) ||
|
||||
mListenerManager->HasListenersFor(nsGkAtoms::onmessage) ||
|
||||
|
@ -96,8 +96,6 @@ class nsDOMDataChannel final : public mozilla::DOMEventTargetHelper,
|
||||
|
||||
virtual nsresult NotBuffered(nsISupports* aContext) override;
|
||||
|
||||
virtual void AppReady();
|
||||
|
||||
// if there are "strong event listeners" or outgoing not sent messages
|
||||
// then this method keeps the object alive when js doesn't have strong
|
||||
// references to it.
|
||||
|
@ -1132,7 +1132,7 @@ PeerConnectionWrapper.prototype = {
|
||||
this.nextDataChannel = new Promise(resolve => {
|
||||
this.ondatachannel = e => {
|
||||
ok(e.channel, message);
|
||||
is(e.channel.readyState, "connecting", "data channel in 'connecting after 'ondatachannel''");
|
||||
is(e.channel.readyState, "open", "data channel in 'open' after 'ondatachannel'");
|
||||
resolve(e.channel);
|
||||
};
|
||||
});
|
||||
@ -1153,12 +1153,7 @@ PeerConnectionWrapper.prototype = {
|
||||
this.expectNegotiationNeeded();
|
||||
}
|
||||
var channel = this._pc.createDataChannel(label, options);
|
||||
if (!this.dataChannels.length) {
|
||||
is(channel.readyState, "connecting", "initial readyState is 'connecting'");
|
||||
} else {
|
||||
// TODO: Bug 1441723 Update firefox to spec.
|
||||
is(channel.readyState, "open", "subsequent readyState is 'open'");
|
||||
}
|
||||
is(channel.readyState, "connecting", "initial readyState is 'connecting'");
|
||||
var wrapper = new DataChannelWrapper(channel, this);
|
||||
this.dataChannels.push(wrapper);
|
||||
return wrapper;
|
||||
|
@ -1127,16 +1127,6 @@ PeerConnectionImpl::CreateDataChannel(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Not a member function so that we don't need to keep the PC live.
|
||||
static void NotifyDataChannel_m(
|
||||
const RefPtr<nsDOMDataChannel>& aChannel,
|
||||
const RefPtr<PeerConnectionObserver>& aObserver) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
JSErrorResult rv;
|
||||
aObserver->NotifyDataChannel(*aChannel, rv);
|
||||
aChannel->AppReady();
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::NotifyDataChannel(
|
||||
already_AddRefed<DataChannel> aChannel) {
|
||||
PC_AUTO_ENTER_API_CALL_NO_CHECK();
|
||||
@ -1150,10 +1140,8 @@ void PeerConnectionImpl::NotifyDataChannel(
|
||||
getter_AddRefs(domchannel));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
RUN_ON_THREAD(
|
||||
mThread,
|
||||
WrapRunnableNM(NotifyDataChannel_m, domchannel.forget(), mPCObserver),
|
||||
NS_DISPATCH_NORMAL);
|
||||
JSErrorResult jrv;
|
||||
mPCObserver->NotifyDataChannel(*domchannel, jrv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1256,18 +1256,12 @@ bool DataChannelConnection::SendDeferredMessages() {
|
||||
uint32_t end = i;
|
||||
do {
|
||||
channel = mStreams[i];
|
||||
// Should already be cleared if closing/closed
|
||||
if (!channel || channel->mBufferedData.IsEmpty()) {
|
||||
i = UpdateCurrentStreamIndex();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Clear if closing/closed
|
||||
if (channel->mState == CLOSED || channel->mState == CLOSING) {
|
||||
channel->mBufferedData.Clear();
|
||||
i = UpdateCurrentStreamIndex();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Send buffered data messages
|
||||
// Warning: This will fail in case ndata is inactive and a previously
|
||||
// deallocated data channel has not been closed properly. If you
|
||||
@ -1375,9 +1369,10 @@ void DataChannelConnection::HandleOpenRequestMessage(
|
||||
if ((channel = FindChannelByStream(stream))) {
|
||||
if (!(channel->mFlags & DATA_CHANNEL_FLAGS_EXTERNAL_NEGOTIATED)) {
|
||||
LOG(
|
||||
("ERROR: HandleOpenRequestMessage: channel for stream %u is in state "
|
||||
"%d instead of CLOSED.",
|
||||
stream, channel->mState));
|
||||
("ERROR: HandleOpenRequestMessage: channel for pre-existing stream "
|
||||
"%u that was not externally negotiated. JS is lying to us, or "
|
||||
"there's an id collision.",
|
||||
stream));
|
||||
/* XXX: some error handling */
|
||||
} else {
|
||||
LOG(("Open for externally negotiated channel %u", stream));
|
||||
@ -1405,20 +1400,18 @@ void DataChannelConnection::HandleOpenRequestMessage(
|
||||
&req->label[ntohs(req->label_length)], ntohs(req->protocol_length)));
|
||||
|
||||
channel =
|
||||
new DataChannel(this, stream, DataChannel::CONNECTING, label, protocol,
|
||||
new DataChannel(this, stream, DataChannel::OPEN, label, protocol,
|
||||
prPolicy, prValue, ordered, false, nullptr, nullptr);
|
||||
mStreams[stream] = channel;
|
||||
|
||||
channel->mState = DataChannel::WAITING_TO_OPEN;
|
||||
|
||||
LOG(("%s: sending ON_CHANNEL_CREATED for %s/%s: %u (state %u)", __FUNCTION__,
|
||||
channel->mLabel.get(), channel->mProtocol.get(), stream,
|
||||
channel->mState));
|
||||
LOG(("%s: sending ON_CHANNEL_CREATED for %s/%s: %u", __FUNCTION__,
|
||||
channel->mLabel.get(), channel->mProtocol.get(), stream));
|
||||
Dispatch(do_AddRef(new DataChannelOnMessageAvailable(
|
||||
DataChannelOnMessageAvailable::ON_CHANNEL_CREATED, this, channel)));
|
||||
|
||||
LOG(("%s: deferring sending ON_CHANNEL_OPEN for %p", __FUNCTION__,
|
||||
channel.get()));
|
||||
channel->AnnounceOpen();
|
||||
|
||||
int error = SendOpenAckMessage(stream);
|
||||
if (error) {
|
||||
@ -1429,9 +1422,6 @@ void DataChannelConnection::HandleOpenRequestMessage(
|
||||
return;
|
||||
}
|
||||
|
||||
// Now process any queued data messages for the channel (which will
|
||||
// themselves likely get queued until we leave WAITING_TO_OPEN, plus any
|
||||
// more that come in before that happens)
|
||||
DeliverQueuedData(stream);
|
||||
}
|
||||
|
||||
@ -1559,11 +1549,6 @@ void DataChannelConnection::HandleDataMessage(const void* data, size_t length,
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore incoming data in case the channel is closed
|
||||
if (channel->mState == CLOSED) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_binary = true;
|
||||
uint8_t bufferFlags;
|
||||
int32_t type;
|
||||
@ -2104,14 +2089,8 @@ void DataChannelConnection::HandleStreamResetEvent(
|
||||
// I believe this is impossible, as we don't have an input stream
|
||||
// yet.
|
||||
|
||||
LOG(("Incoming: Channel %u closed, state %d", channel->mStream,
|
||||
channel->mState));
|
||||
ASSERT_WEBRTC(channel->mState == DataChannel::OPEN ||
|
||||
channel->mState == DataChannel::CLOSING ||
|
||||
channel->mState == DataChannel::CONNECTING ||
|
||||
channel->mState == DataChannel::WAITING_TO_OPEN);
|
||||
if (channel->mState == DataChannel::OPEN ||
|
||||
channel->mState == DataChannel::WAITING_TO_OPEN) {
|
||||
LOG(("Incoming: Channel %u closed", channel->mStream));
|
||||
if (mStreams[channel->mStream]) {
|
||||
// Mark the stream for reset (the reset is sent below)
|
||||
ResetOutgoingStream(channel->mStream);
|
||||
}
|
||||
@ -2119,7 +2098,6 @@ void DataChannelConnection::HandleStreamResetEvent(
|
||||
|
||||
LOG(("Disconnected DataChannel %p from connection %p",
|
||||
(void*)channel.get(), (void*)channel->mConnection.get()));
|
||||
// This sends ON_CHANNEL_CLOSED to mainthread
|
||||
channel->StreamClosedLocked();
|
||||
} else {
|
||||
LOG(("Can't find incoming channel %d", i));
|
||||
@ -2194,14 +2172,11 @@ void DataChannelConnection::HandleStreamChangeEvent(
|
||||
channel = mStreams[i];
|
||||
if (!channel) continue;
|
||||
|
||||
if ((channel->mState == CONNECTING) &&
|
||||
(channel->mStream == INVALID_STREAM)) {
|
||||
if (channel->mStream == INVALID_STREAM) {
|
||||
if ((strchg->strchange_flags & SCTP_STREAM_CHANGE_DENIED) ||
|
||||
(strchg->strchange_flags & SCTP_STREAM_CHANGE_FAILED)) {
|
||||
/* XXX: Signal to the other end. */
|
||||
channel->mState = CLOSED;
|
||||
Dispatch(do_AddRef(new DataChannelOnMessageAvailable(
|
||||
DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this, channel)));
|
||||
channel->AnnounceClosed();
|
||||
// maybe fire onError (bug 843625)
|
||||
} else {
|
||||
stream = FindFreeStream();
|
||||
@ -2218,19 +2193,11 @@ void DataChannelConnection::HandleStreamChangeEvent(
|
||||
LOG(("SendOpenRequest failed, error = %d", error));
|
||||
// Close the channel, inform the user
|
||||
mStreams[channel->mStream] = nullptr;
|
||||
channel->mState = CLOSED;
|
||||
channel->AnnounceClosed();
|
||||
// Don't need to reset; we didn't open it
|
||||
Dispatch(do_AddRef(new DataChannelOnMessageAvailable(
|
||||
DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this,
|
||||
channel)));
|
||||
} else {
|
||||
channel->mState = OPEN;
|
||||
channel->mFlags |= DATA_CHANNEL_FLAGS_READY;
|
||||
LOG(("%s: sending ON_CHANNEL_OPEN for %p", __FUNCTION__,
|
||||
channel.get()));
|
||||
Dispatch(do_AddRef(new DataChannelOnMessageAvailable(
|
||||
DataChannelOnMessageAvailable::ON_CHANNEL_OPEN, this,
|
||||
channel)));
|
||||
channel->AnnounceOpen();
|
||||
}
|
||||
} else {
|
||||
/* We will not find more ... */
|
||||
@ -2484,7 +2451,7 @@ already_AddRefed<DataChannel> DataChannelConnection::OpenFinish(
|
||||
|
||||
#ifdef TEST_QUEUED_DATA
|
||||
// It's painful to write a test for this...
|
||||
channel->mState = OPEN;
|
||||
channel->AnnounceOpen();
|
||||
channel->mFlags |= DATA_CHANNEL_FLAGS_READY;
|
||||
SendDataMsgInternalOrBuffer(channel, "Help me!", 8,
|
||||
DATA_CHANNEL_PPID_DOMSTRING);
|
||||
@ -2505,36 +2472,30 @@ already_AddRefed<DataChannel> DataChannelConnection::OpenFinish(
|
||||
if (channel->mFlags & DATA_CHANNEL_FLAGS_FINISH_OPEN) {
|
||||
// We already returned the channel to the app.
|
||||
NS_ERROR("Failed to send open request");
|
||||
Dispatch(do_AddRef(new DataChannelOnMessageAvailable(
|
||||
DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this, channel)));
|
||||
channel->AnnounceClosed();
|
||||
}
|
||||
// If we haven't returned the channel yet, it will get destroyed when we
|
||||
// exit this function.
|
||||
mStreams[stream] = nullptr;
|
||||
channel->mStream = INVALID_STREAM;
|
||||
// we'll be destroying the channel
|
||||
channel->mState = CLOSED;
|
||||
return nullptr;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
// Either externally negotiated or we sent Open
|
||||
channel->mState = OPEN;
|
||||
channel->mFlags |= DATA_CHANNEL_FLAGS_READY;
|
||||
// FIX? Move into DOMDataChannel? I don't think we can send it yet here
|
||||
LOG(("%s: sending ON_CHANNEL_OPEN for %p", __FUNCTION__, channel.get()));
|
||||
Dispatch(do_AddRef(new DataChannelOnMessageAvailable(
|
||||
DataChannelOnMessageAvailable::ON_CHANNEL_OPEN, this, channel)));
|
||||
channel->AnnounceOpen();
|
||||
|
||||
return channel.forget();
|
||||
|
||||
request_error_cleanup:
|
||||
channel->mState = CLOSED;
|
||||
if (channel->mFlags & DATA_CHANNEL_FLAGS_FINISH_OPEN) {
|
||||
// We already returned the channel to the app.
|
||||
NS_ERROR("Failed to request more streams");
|
||||
Dispatch(do_AddRef(new DataChannelOnMessageAvailable(
|
||||
DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this, channel)));
|
||||
channel->AnnounceClosed();
|
||||
return channel.forget();
|
||||
}
|
||||
// we'll be destroying the channel, but it never really got set up
|
||||
@ -2694,7 +2655,7 @@ int DataChannelConnection::SendDataMsgInternalOrBuffer(DataChannel& channel,
|
||||
const uint8_t* data,
|
||||
size_t len,
|
||||
uint32_t ppid) {
|
||||
if (NS_WARN_IF(channel.mState != OPEN && channel.mState != CONNECTING)) {
|
||||
if (NS_WARN_IF(channel.mReadyState != OPEN)) {
|
||||
return EINVAL; // TODO: Find a better error code
|
||||
}
|
||||
|
||||
@ -3006,8 +2967,8 @@ void DataChannelConnection::CloseInt(DataChannel* aChannel) {
|
||||
LOG(("Connection %p/Channel %p: Closing stream %u",
|
||||
channel->mConnection.get(), channel.get(), channel->mStream));
|
||||
// re-test since it may have closed before the lock was grabbed
|
||||
if (aChannel->mState == CLOSED || aChannel->mState == CLOSING) {
|
||||
LOG(("Channel already closing/closed (%u)", aChannel->mState));
|
||||
if (aChannel->mReadyState == CLOSED || aChannel->mReadyState == CLOSING) {
|
||||
LOG(("Channel already closing/closed (%u)", aChannel->mReadyState));
|
||||
if (mState == CLOSED && channel->mStream != INVALID_STREAM) {
|
||||
// called from CloseAll()
|
||||
// we're not going to hang around waiting any more
|
||||
@ -3026,7 +2987,7 @@ void DataChannelConnection::CloseInt(DataChannel* aChannel) {
|
||||
SendOutgoingStreamReset();
|
||||
}
|
||||
}
|
||||
aChannel->mState = CLOSING;
|
||||
aChannel->mReadyState = CLOSING;
|
||||
if (mState == CLOSED) {
|
||||
// we're not going to hang around waiting
|
||||
channel->StreamClosedLocked();
|
||||
@ -3077,7 +3038,7 @@ DataChannel::~DataChannel() {
|
||||
// NS_ASSERTION since this is more "I think I caught all the cases that
|
||||
// can cause this" than a true kill-the-program assertion. If this is
|
||||
// wrong, nothing bad happens. A worst it's a leak.
|
||||
NS_ASSERTION(mState == CLOSED || mState == CLOSING,
|
||||
NS_ASSERTION(mReadyState == CLOSED || mReadyState == CLOSING,
|
||||
"unexpected state in ~DataChannel");
|
||||
}
|
||||
|
||||
@ -3097,10 +3058,9 @@ void DataChannel::StreamClosedLocked() {
|
||||
LOG(("Destroying Data channel %u", mStream));
|
||||
MOZ_ASSERT_IF(mStream != INVALID_STREAM,
|
||||
!mConnection->FindChannelByStream(mStream));
|
||||
// Spec doesn't say to mess with the stream id...
|
||||
mStream = INVALID_STREAM;
|
||||
mState = CLOSED;
|
||||
mMainThreadEventTarget->Dispatch(do_AddRef(new DataChannelOnMessageAvailable(
|
||||
DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, mConnection, this)));
|
||||
AnnounceClosed();
|
||||
// We leave mConnection live until the DOM releases us, to avoid races
|
||||
}
|
||||
|
||||
@ -3111,7 +3071,7 @@ void DataChannel::ReleaseConnection() {
|
||||
|
||||
void DataChannel::SetListener(DataChannelListener* aListener,
|
||||
nsISupports* aContext) {
|
||||
MutexAutoLock mLock(mListenerLock);
|
||||
ASSERT_WEBRTC(NS_IsMainThread());
|
||||
mContext = aContext;
|
||||
mListener = aListener;
|
||||
}
|
||||
@ -3159,6 +3119,36 @@ void DataChannel::DecrementBufferedAmount(uint32_t aSize) {
|
||||
}));
|
||||
}
|
||||
|
||||
void DataChannel::AnnounceOpen() {
|
||||
mMainThreadEventTarget->Dispatch(NS_NewRunnableFunction(
|
||||
"DataChannel::AnnounceOpen", [this, self = RefPtr<DataChannel>(this)] {
|
||||
// Special-case; spec says to put brand-new remote-created DataChannel
|
||||
// in "open", but queue the firing of the "open" event.
|
||||
if (mReadyState != CLOSING && mReadyState != CLOSED && mListener) {
|
||||
mReadyState = OPEN;
|
||||
LOG(("%s: sending ON_CHANNEL_OPEN for %s/%s: %u", __FUNCTION__,
|
||||
mLabel.get(), mProtocol.get(), mStream));
|
||||
mListener->OnChannelConnected(mContext);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
void DataChannel::AnnounceClosed() {
|
||||
mMainThreadEventTarget->Dispatch(NS_NewRunnableFunction(
|
||||
"DataChannel::AnnounceClosed", [this, self = RefPtr<DataChannel>(this)] {
|
||||
if (mReadyState == CLOSED) {
|
||||
return;
|
||||
}
|
||||
mReadyState = CLOSED;
|
||||
mBufferedData.Clear();
|
||||
if (mListener) {
|
||||
LOG(("%s: sending ON_CHANNEL_CLOSED for %s/%s: %u", __FUNCTION__,
|
||||
mLabel.get(), mProtocol.get(), mStream));
|
||||
mListener->OnChannelClosed(mContext);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
void DataChannel::SendMsg(const nsACString& aMsg, ErrorResult& aRv) {
|
||||
if (!EnsureValidStream(aRv)) {
|
||||
return;
|
||||
@ -3225,34 +3215,6 @@ dom::Nullable<uint16_t> DataChannel::GetMaxRetransmits() const {
|
||||
return dom::Nullable<uint16_t>();
|
||||
}
|
||||
|
||||
// May be called from another (i.e. Main) thread!
|
||||
void DataChannel::AppReady() {
|
||||
ENSURE_DATACONNECTION;
|
||||
|
||||
MutexAutoLock lock(mConnection->mLock);
|
||||
|
||||
mFlags |= DATA_CHANNEL_FLAGS_READY;
|
||||
if (mState == WAITING_TO_OPEN) {
|
||||
mState = OPEN;
|
||||
mMainThreadEventTarget->Dispatch(
|
||||
do_AddRef(new DataChannelOnMessageAvailable(
|
||||
DataChannelOnMessageAvailable::ON_CHANNEL_OPEN, mConnection,
|
||||
this)));
|
||||
for (uint32_t i = 0; i < mQueuedMessages.Length(); ++i) {
|
||||
nsCOMPtr<nsIRunnable> runnable = mQueuedMessages[i];
|
||||
MOZ_ASSERT(runnable);
|
||||
mMainThreadEventTarget->Dispatch(runnable.forget());
|
||||
}
|
||||
} else {
|
||||
NS_ASSERTION(mQueuedMessages.IsEmpty(),
|
||||
"Shouldn't have queued messages if not WAITING_TO_OPEN");
|
||||
}
|
||||
mQueuedMessages.Clear();
|
||||
mQueuedMessages.Compact();
|
||||
// We never use it again... We could even allocate the array in the odd
|
||||
// cases we need it.
|
||||
}
|
||||
|
||||
uint32_t DataChannel::GetBufferedAmountLowThreshold() {
|
||||
return mBufferedThreshold;
|
||||
}
|
||||
@ -3264,13 +3226,8 @@ void DataChannel::SetBufferedAmountLowThreshold(uint32_t aThreshold) {
|
||||
|
||||
// Called with mLock locked!
|
||||
void DataChannel::SendOrQueue(DataChannelOnMessageAvailable* aMessage) {
|
||||
if (!(mFlags & DATA_CHANNEL_FLAGS_READY) &&
|
||||
(mState == CONNECTING || mState == WAITING_TO_OPEN)) {
|
||||
mQueuedMessages.AppendElement(aMessage);
|
||||
} else {
|
||||
nsCOMPtr<nsIRunnable> runnable = aMessage;
|
||||
mMainThreadEventTarget->Dispatch(runnable.forget());
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> runnable = aMessage;
|
||||
mMainThreadEventTarget->Dispatch(runnable.forget());
|
||||
}
|
||||
|
||||
bool DataChannel::EnsureValidStream(ErrorResult& aRv) {
|
||||
|
@ -367,26 +367,19 @@ class DataChannelConnection final : public net::NeckoTargetHolder
|
||||
|
||||
class DataChannel {
|
||||
public:
|
||||
enum {
|
||||
CONNECTING = 0U,
|
||||
OPEN = 1U,
|
||||
CLOSING = 2U,
|
||||
CLOSED = 3U,
|
||||
WAITING_TO_OPEN = 4U
|
||||
};
|
||||
enum { CONNECTING = 0U, OPEN = 1U, CLOSING = 2U, CLOSED = 3U };
|
||||
|
||||
DataChannel(DataChannelConnection* connection, uint16_t stream,
|
||||
uint16_t state, const nsACString& label,
|
||||
const nsACString& protocol, uint16_t policy, uint32_t value,
|
||||
bool ordered, bool negotiated, DataChannelListener* aListener,
|
||||
nsISupports* aContext)
|
||||
: mListenerLock("netwerk::sctp::DataChannel"),
|
||||
mListener(aListener),
|
||||
: mListener(aListener),
|
||||
mContext(aContext),
|
||||
mConnection(connection),
|
||||
mLabel(label),
|
||||
mProtocol(protocol),
|
||||
mState(state),
|
||||
mReadyState(state),
|
||||
mStream(stream),
|
||||
mPrPolicy(policy),
|
||||
mPrValue(value),
|
||||
@ -463,14 +456,14 @@ class DataChannel {
|
||||
uint32_t GetBufferedAmountLowThreshold();
|
||||
void SetBufferedAmountLowThreshold(uint32_t aThreshold);
|
||||
|
||||
void AnnounceOpen();
|
||||
// TODO(bug 843625): Optionally pass an error here.
|
||||
void AnnounceClosed();
|
||||
|
||||
// Find out state
|
||||
uint16_t GetReadyState() {
|
||||
if (mConnection) {
|
||||
MutexAutoLock lock(mConnection->mLock);
|
||||
if (mState == WAITING_TO_OPEN) return CONNECTING;
|
||||
return mState;
|
||||
}
|
||||
return CLOSED;
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mReadyState;
|
||||
}
|
||||
|
||||
void GetLabel(nsAString& aLabel) { CopyUTF8toUTF16(mLabel, aLabel); }
|
||||
@ -479,12 +472,10 @@ class DataChannel {
|
||||
}
|
||||
uint16_t GetStream() { return mStream; }
|
||||
|
||||
void AppReady();
|
||||
|
||||
void SendOrQueue(DataChannelOnMessageAvailable* aMessage);
|
||||
|
||||
protected:
|
||||
Mutex mListenerLock; // protects mListener and mContext
|
||||
// These are both mainthread only
|
||||
DataChannelListener* mListener;
|
||||
nsCOMPtr<nsISupports> mContext;
|
||||
|
||||
@ -498,7 +489,8 @@ class DataChannel {
|
||||
RefPtr<DataChannelConnection> mConnection;
|
||||
nsCString mLabel;
|
||||
nsCString mProtocol;
|
||||
uint16_t mState;
|
||||
// This is mainthread only
|
||||
uint16_t mReadyState;
|
||||
uint16_t mStream;
|
||||
uint16_t mPrPolicy;
|
||||
uint32_t mPrValue;
|
||||
@ -514,7 +506,6 @@ class DataChannel {
|
||||
nsCString mRecvBuffer;
|
||||
nsTArray<nsAutoPtr<BufferedOutgoingMsg>>
|
||||
mBufferedData; // GUARDED_BY(mConnection->mLock)
|
||||
nsTArray<nsCOMPtr<nsIRunnable>> mQueuedMessages;
|
||||
nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
|
||||
};
|
||||
|
||||
@ -527,8 +518,6 @@ class DataChannelOnMessageAvailable : public Runnable {
|
||||
ON_CONNECTION,
|
||||
ON_DISCONNECTED,
|
||||
ON_CHANNEL_CREATED,
|
||||
ON_CHANNEL_OPEN,
|
||||
ON_CHANNEL_CLOSED,
|
||||
ON_DATA_STRING,
|
||||
ON_DATA_BINARY,
|
||||
}; /* types */
|
||||
@ -575,54 +564,42 @@ class DataChannelOnMessageAvailable : public Runnable {
|
||||
switch (mType) {
|
||||
case ON_DATA_STRING:
|
||||
case ON_DATA_BINARY:
|
||||
case ON_CHANNEL_OPEN:
|
||||
case ON_CHANNEL_CLOSED: {
|
||||
MutexAutoLock lock(mChannel->mListenerLock);
|
||||
if (!mChannel->mListener) {
|
||||
DATACHANNEL_LOG((
|
||||
"DataChannelOnMessageAvailable (%d) with null Listener!", mType));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
switch (mType) {
|
||||
case ON_DATA_STRING:
|
||||
mChannel->mListener->OnMessageAvailable(mChannel->mContext, mData);
|
||||
break;
|
||||
case ON_DATA_BINARY:
|
||||
mChannel->mListener->OnBinaryMessageAvailable(mChannel->mContext,
|
||||
mData);
|
||||
break;
|
||||
case ON_CHANNEL_OPEN:
|
||||
mChannel->mListener->OnChannelConnected(mChannel->mContext);
|
||||
break;
|
||||
case ON_CHANNEL_CLOSED:
|
||||
mChannel->mListener->OnChannelClosed(mChannel->mContext);
|
||||
break;
|
||||
if (mChannel->GetReadyState() == DataChannel::CLOSED ||
|
||||
mChannel->GetReadyState() == DataChannel::CLOSING) {
|
||||
// Closed by JS, probably
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mType == ON_DATA_STRING) {
|
||||
mChannel->mListener->OnMessageAvailable(mChannel->mContext, mData);
|
||||
} else {
|
||||
mChannel->mListener->OnBinaryMessageAvailable(mChannel->mContext,
|
||||
mData);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ON_DISCONNECTED:
|
||||
// If we've disconnected, make sure we close all the streams - from
|
||||
// mainthread!
|
||||
mConnection->CloseAll();
|
||||
MOZ_FALLTHROUGH;
|
||||
break;
|
||||
case ON_CHANNEL_CREATED:
|
||||
case ON_CONNECTION:
|
||||
// WeakPtr - only used/modified/nulled from MainThread so we can use a
|
||||
// WeakPtr here
|
||||
if (!mConnection->mListener) {
|
||||
DATACHANNEL_LOG(
|
||||
("DataChannelOnMessageAvailable (%d) with null Listener", mType));
|
||||
DATACHANNEL_LOG((
|
||||
"DataChannelOnMessageAvailable (%d) with null Listener!", mType));
|
||||
return NS_OK;
|
||||
}
|
||||
switch (mType) {
|
||||
case ON_CHANNEL_CREATED:
|
||||
// important to give it an already_AddRefed pointer!
|
||||
mConnection->mListener->NotifyDataChannel(mChannel.forget());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// important to give it an already_AddRefed pointer!
|
||||
mConnection->mListener->NotifyDataChannel(mChannel.forget());
|
||||
break;
|
||||
case ON_CONNECTION:
|
||||
// TODO: Notify someday? How? What does the spec say about this?
|
||||
break;
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -31,10 +31,6 @@
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1547106
|
||||
|
||||
[New data channel should be in the connecting state after creation (after connection establishment)]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1548636
|
||||
|
||||
[Reusing a data channel id that is in use should throw OperationError]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1547106
|
||||
|
@ -3,22 +3,10 @@
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1531100
|
||||
|
||||
[Data channel event should fire when new data channel is announced to the remote peer]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1551589
|
||||
|
||||
[In-band negotiated channel created on remote peer should match the same (default) configuration as local peer]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1529695
|
||||
|
||||
[Open event should not be raised when sending and immediately closing the channel in the datachannel event]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1551589
|
||||
|
||||
[Should be able to send data in a datachannel event handler]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1551589
|
||||
|
||||
[In-band negotiated channel created on remote peer should match the same configuration as local peer]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1551589
|
||||
|
Loading…
Reference in New Issue
Block a user