/* -*- 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/. */
// Since we've moved the windows.h include down here, we have to explicitly // undef GetBinaryType, otherwise we'll get really odd conflicts #ifdef GetBinaryType # undef GetBinaryType #endif
nsDOMDataChannel::~nsDOMDataChannel() { // Don't call us anymore! Likely isn't an issue (or maybe just less of // one) once we block GC until all the (appropriate) onXxxx handlers // are dropped. (See WebRTC spec)
DC_DEBUG(("%p: Close()ing %p", this, mDataChannel.get()));
mDataChannel->SetListener(nullptr, nullptr);
mDataChannel->Close();
}
// Now grovel through the objects to get a usable origin for onMessage
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aDOMWindow);
NS_ENSURE_STATE(sgo);
nsCOMPtr<nsIScriptContext> scriptContext = sgo->GetContext();
NS_ENSURE_STATE(scriptContext);
nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal(
do_QueryInterface(aDOMWindow));
NS_ENSURE_STATE(scriptPrincipal);
nsCOMPtr<nsIPrincipal> principal = scriptPrincipal->GetPrincipal();
NS_ENSURE_STATE(principal);
// Attempt to kill "ghost" DataChannel (if one can happen): but usually too // early for check to fail
rv = CheckCurrentGlobalCorrectness();
NS_ENSURE_SUCCESS(rv, rv);
// Most of the GetFoo()/SetFoo()s don't need to touch shared resources and // are safe after Close() void nsDOMDataChannel::GetLabel(nsAString& aLabel) {
mDataChannel->GetLabel(aLabel);
}
mozilla::dom::Nullable<uint16_t> nsDOMDataChannel::GetId() const {
mozilla::dom::Nullable<uint16_t> result = mDataChannel->GetStream(); if (result.Value() == 65535) {
result.SetNull();
} return result;
}
// XXX should be GetType()? Open question for the spec bool nsDOMDataChannel::Reliable() const { return mDataChannel->GetType() ==
mozilla::DataChannelReliabilityPolicy::Reliable;
}
// All of the following is copy/pasted from WebSocket.cpp. void nsDOMDataChannel::Send(const nsAString& aData, ErrorResult& aRv) { if (!CheckReadyState(aRv)) { return;
}
nsAutoCString msgString; if (!AppendUTF16toUTF8(aData, msgString, mozilla::fallible_t())) {
aRv.Throw(NS_ERROR_FILE_TOO_BIG); return;
}
mDataChannel->SendMsg(msgString, aRv);
}
void nsDOMDataChannel::Send(Blob& aData, ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
if (!CheckReadyState(aRv)) { return;
}
nsCOMPtr<nsIInputStream> msgStream;
aData.CreateInputStream(getter_AddRefs(msgStream), aRv); if (NS_WARN_IF(aRv.Failed())) { return;
}
uint64_t msgLength = aData.GetSize(aRv); if (NS_WARN_IF(aRv.Failed())) { return;
}
if (msgLength > UINT32_MAX) {
aRv.Throw(NS_ERROR_FILE_TOO_BIG); return;
}
mDataChannel->SendBinaryBlob(aData, aRv);
}
void nsDOMDataChannel::Send(const ArrayBuffer& aData, ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
if (!CheckReadyState(aRv)) { return;
}
nsCString msgString; if (!aData.AppendDataTo(msgString)) {
aRv.Throw(NS_ERROR_FILE_TOO_BIG); return;
}
mDataChannel->SendBinaryMsg(msgString, aRv);
}
void nsDOMDataChannel::Send(const ArrayBufferView& aData, ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
if (!CheckReadyState(aRv)) { return;
}
nsCString msgString; if (!aData.AppendDataTo(msgString)) {
aRv.Throw(NS_ERROR_FILE_TOO_BIG); return;
}
mDataChannel->SendBinaryMsg(msgString, aRv);
}
bool nsDOMDataChannel::CheckReadyState(ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread());
DataChannelState state = DataChannelState::Closed; if (!mSentClose) {
state = mDataChannel->GetReadyState();
}
// In reality, the DataChannel protocol allows this, but we want it to // look like WebSockets if (state == DataChannelState::Connecting) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); returnfalse;
}
if (state == DataChannelState::Closing || state == DataChannelState::Closed) { returnfalse;
}
MOZ_ASSERT(state == DataChannelState::Open, "Unknown state in nsDOMDataChannel::Send");
nsresult nsDOMDataChannel::OnChannelClosed(nsISupports* aContext) {
nsresult rv; // so we don't have to worry if we're notified from different paths in // the underlying code if (!mSentClose) { // Ok, we're done with it.
mDataChannel->ReleaseConnection();
DC_DEBUG(("%p(%p): %s - Dispatching\n", this, (void*)mDataChannel,
__FUNCTION__));
rv = OnSimpleEvent(aContext, u"close"_ns); // no more events can happen
mSentClose = true;
} else {
rv = NS_OK;
}
DontKeepAliveAnyMore(); return rv;
}
nsresult nsDOMDataChannel::NotBuffered(nsISupports* aContext) { // In the rare case that we held off GC to let the buffer drain
UpdateMustKeepAlive(); return NS_OK;
}
//----------------------------------------------------------------------------- // Methods that keep alive the DataChannel object when: // 1. the object has registered event listeners that can be triggered // ("strong event listeners"); // 2. there are outgoing not sent messages. //-----------------------------------------------------------------------------
if (mSelfRef) { // Since we're on MainThread, force an eventloop trip to avoid deleting // ourselves.
ReleaseSelf();
}
mCheckMustKeepAlive = false;
}
void nsDOMDataChannel::ReleaseSelf() { // release our self-reference (safely) by putting it in an event (always)
NS_ReleaseOnMainThread("nsDOMDataChannel::mSelfRef", mSelfRef.forget(), true);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.