зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound.
This commit is contained in:
Коммит
4f23c7f5c8
|
@ -1,10 +1,21 @@
|
|||
/* 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 "domstubs.idl"
|
||||
|
||||
#include "nsIDOMEventTarget.idl"
|
||||
|
||||
%{C++
|
||||
#ifdef GetBinaryType
|
||||
// Windows apparently has a #define for GetBinaryType...
|
||||
#undef GetBinaryType
|
||||
#endif
|
||||
%}
|
||||
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, builtinclass, uuid(1aed816d-1156-414e-8fe2-f01daa6021f0)]
|
||||
[scriptable, builtinclass, uuid(4410f28d-c9eb-481d-a47e-e7ef49f382c8)]
|
||||
interface nsIDOMDataChannel : nsIDOMEventTarget
|
||||
{
|
||||
readonly attribute DOMString label;
|
||||
|
@ -25,14 +36,4 @@ interface nsIDOMDataChannel : nsIDOMEventTarget
|
|||
attribute DOMString binaryType;
|
||||
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Transmits data to other end of the connection.
|
||||
* @param data The data to be transmitted. Arraybuffers and Blobs are sent as
|
||||
* binary data. Strings are sent as UTF-8 text data. Other types are
|
||||
* converted to a String and sent as a String.
|
||||
* @return if the connection is still established and the data was queued or
|
||||
* sent successfully.
|
||||
*/
|
||||
void send(in nsIVariant data);
|
||||
};
|
||||
|
|
|
@ -35,7 +35,10 @@ EXPORTS += [
|
|||
]
|
||||
|
||||
if CONFIG['MOZ_WEBRTC']:
|
||||
EXPORTS += ['nsDOMDataChannel.h']
|
||||
EXPORTS += [
|
||||
'nsDOMDataChannel.h',
|
||||
'nsDOMDataChannelDeclarations.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Attr.h',
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* 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 "nsDOMDataChannel.h"
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
#define FORCE_PR_LOG
|
||||
#endif
|
||||
|
@ -18,101 +20,40 @@ extern PRLogModuleInfo* GetDataChannelLog();
|
|||
#define LOG(args) PR_LOG(GetDataChannelLog(), PR_LOG_DEBUG, args)
|
||||
|
||||
|
||||
#include "nsDOMDataChannel.h"
|
||||
#include "nsDOMDataChannelDeclarations.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsIJSNativeInitializer.h"
|
||||
#include "nsIDOMDataChannel.h"
|
||||
#include "nsIDOMMessageEvent.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
|
||||
#include "js/Value.h"
|
||||
|
||||
#include "nsError.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsDOMFile.h"
|
||||
|
||||
#include "DataChannel.h"
|
||||
|
||||
#ifdef GetBinaryType
|
||||
// Windows apparently has a #define for GetBinaryType...
|
||||
#undef GetBinaryType
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
class nsDOMDataChannel : public nsDOMEventTargetHelper,
|
||||
public nsIDOMDataChannel,
|
||||
public mozilla::DataChannelListener
|
||||
nsDOMDataChannel::~nsDOMDataChannel()
|
||||
{
|
||||
public:
|
||||
nsDOMDataChannel(already_AddRefed<mozilla::DataChannel> aDataChannel)
|
||||
: mDataChannel(aDataChannel)
|
||||
, mBinaryType(DC_BINARY_TYPE_BLOB)
|
||||
{}
|
||||
// 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)
|
||||
LOG(("Close()ing %p", mDataChannel.get()));
|
||||
mDataChannel->SetListener(nullptr, nullptr);
|
||||
mDataChannel->Close();
|
||||
}
|
||||
|
||||
~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)
|
||||
LOG(("Close()ing %p", mDataChannel.get()));
|
||||
mDataChannel->SetListener(nullptr, nullptr);
|
||||
mDataChannel->Close();
|
||||
}
|
||||
|
||||
nsresult Init(nsPIDOMWindow* aDOMWindow);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDOMDATACHANNEL
|
||||
|
||||
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMDataChannel,
|
||||
nsDOMEventTargetHelper)
|
||||
|
||||
nsresult
|
||||
DoOnMessageAvailable(const nsACString& aMessage, bool aBinary);
|
||||
|
||||
virtual nsresult
|
||||
OnMessageAvailable(nsISupports* aContext, const nsACString& aMessage);
|
||||
|
||||
virtual nsresult
|
||||
OnBinaryMessageAvailable(nsISupports* aContext, const nsACString& aMessage);
|
||||
|
||||
virtual nsresult OnSimpleEvent(nsISupports* aContext, const nsAString& aName);
|
||||
|
||||
virtual nsresult
|
||||
OnChannelConnected(nsISupports* aContext);
|
||||
|
||||
virtual nsresult
|
||||
OnChannelClosed(nsISupports* aContext);
|
||||
|
||||
virtual void
|
||||
AppReady();
|
||||
|
||||
private:
|
||||
// Get msg info out of JS variable being sent (string, arraybuffer, blob)
|
||||
nsresult GetSendParams(nsIVariant *aData, nsCString &aStringOut,
|
||||
nsCOMPtr<nsIInputStream> &aStreamOut,
|
||||
bool &aIsBinary, uint32_t &aOutgoingLength);
|
||||
|
||||
// Owning reference
|
||||
nsRefPtr<mozilla::DataChannel> mDataChannel;
|
||||
nsString mOrigin;
|
||||
enum
|
||||
{
|
||||
DC_BINARY_TYPE_ARRAYBUFFER,
|
||||
DC_BINARY_TYPE_BLOB,
|
||||
} mBinaryType;
|
||||
};
|
||||
|
||||
DOMCI_DATA(DataChannel, nsDOMDataChannel)
|
||||
/* virtual */ JSObject*
|
||||
nsDOMDataChannel::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
return DataChannelBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDataChannel,
|
||||
nsDOMEventTargetHelper)
|
||||
|
@ -127,7 +68,6 @@ NS_IMPL_RELEASE_INHERITED(nsDOMDataChannel, nsDOMEventTargetHelper)
|
|||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMDataChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMDataChannel)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DataChannel)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
nsresult
|
||||
|
@ -185,28 +125,53 @@ nsDOMDataChannel::GetProtocol(nsAString& aProtocol)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
nsDOMDataChannel::Stream() const
|
||||
{
|
||||
return mDataChannel->GetStream();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDataChannel::GetStream(uint16_t *aStream)
|
||||
{
|
||||
mDataChannel->GetStream(aStream);
|
||||
*aStream = Stream();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX should be GetType()? Open question for the spec
|
||||
bool
|
||||
nsDOMDataChannel::Reliable() const
|
||||
{
|
||||
return mDataChannel->GetType() == mozilla::DataChannelConnection::RELIABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDataChannel::GetReliable(bool* aReliable)
|
||||
{
|
||||
*aReliable = (mDataChannel->GetType() == mozilla::DataChannelConnection::RELIABLE);
|
||||
*aReliable = Reliable();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDOMDataChannel::Ordered() const
|
||||
{
|
||||
return mDataChannel->GetOrdered();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDataChannel::GetOrdered(bool* aOrdered)
|
||||
{
|
||||
*aOrdered = mDataChannel->GetOrdered();
|
||||
*aOrdered = Ordered();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RTCDataChannelState
|
||||
nsDOMDataChannel::ReadyState() const
|
||||
{
|
||||
return static_cast<RTCDataChannelState>(mDataChannel->GetReadyState());
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDataChannel::GetReadyState(nsAString& aReadyState)
|
||||
{
|
||||
|
@ -225,10 +190,16 @@ nsDOMDataChannel::GetReadyState(nsAString& aReadyState)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
nsDOMDataChannel::BufferedAmount() const
|
||||
{
|
||||
return mDataChannel->GetBufferedAmount();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDataChannel::GetBufferedAmount(uint32_t* aBufferedAmount)
|
||||
{
|
||||
*aBufferedAmount = mDataChannel->GetBufferedAmount();
|
||||
*aBufferedAmount = BufferedAmount();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -267,9 +238,73 @@ nsDOMDataChannel::Close()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Almost a clone of nsWebSocketChannel::Send()
|
||||
NS_IMETHODIMP
|
||||
nsDOMDataChannel::Send(nsIVariant* aData)
|
||||
// All of the following is copy/pasted from WebSocket.cpp.
|
||||
void
|
||||
nsDOMDataChannel::Send(const nsAString& aData, ErrorResult& aRv)
|
||||
{
|
||||
NS_ConvertUTF16toUTF8 msgString(aData);
|
||||
Send(nullptr, msgString, msgString.Length(), false, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMDataChannel::Send(nsIDOMBlob* aData, ErrorResult& aRv)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
|
||||
|
||||
nsCOMPtr<nsIInputStream> msgStream;
|
||||
nsresult rv = aData->GetInternalStream(getter_AddRefs(msgStream));
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t msgLength;
|
||||
rv = aData->GetSize(&msgLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msgLength > UINT32_MAX) {
|
||||
aRv.Throw(NS_ERROR_FILE_TOO_BIG);
|
||||
return;
|
||||
}
|
||||
|
||||
Send(msgStream, EmptyCString(), msgLength, true, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMDataChannel::Send(ArrayBuffer& aData, ErrorResult& aRv)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
|
||||
|
||||
MOZ_ASSERT(sizeof(*aData.Data()) == 1);
|
||||
uint32_t len = aData.Length();
|
||||
char* data = reinterpret_cast<char*>(aData.Data());
|
||||
|
||||
nsDependentCSubstring msgString(data, len);
|
||||
Send(nullptr, msgString, len, true, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMDataChannel::Send(ArrayBufferView& aData, ErrorResult& aRv)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
|
||||
|
||||
MOZ_ASSERT(sizeof(*aData.Data()) == 1);
|
||||
uint32_t len = aData.Length();
|
||||
char* data = reinterpret_cast<char*>(aData.Data());
|
||||
|
||||
nsDependentCSubstring msgString(data, len);
|
||||
Send(nullptr, msgString, len, true, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMDataChannel::Send(nsIInputStream* aMsgStream,
|
||||
const nsACString& aMsgString,
|
||||
uint32_t aMsgLength,
|
||||
bool aIsBinary,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
uint16_t state = mDataChannel->GetReadyState();
|
||||
|
@ -277,110 +312,31 @@ nsDOMDataChannel::Send(nsIVariant* aData)
|
|||
// In reality, the DataChannel protocol allows this, but we want it to
|
||||
// look like WebSockets
|
||||
if (state == mozilla::DataChannel::CONNECTING) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString msgString;
|
||||
nsCOMPtr<nsIInputStream> msgStream;
|
||||
bool isBinary;
|
||||
uint32_t msgLen;
|
||||
nsresult rv = GetSendParams(aData, msgString, msgStream, isBinary, msgLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (state == mozilla::DataChannel::CLOSING ||
|
||||
state == mozilla::DataChannel::CLOSED) {
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(state == mozilla::DataChannel::OPEN,
|
||||
"Unknown state in nsWebSocket::Send");
|
||||
"Unknown state in nsDOMDataChannel::Send");
|
||||
|
||||
int32_t sent;
|
||||
if (msgStream) {
|
||||
sent = mDataChannel->SendBinaryStream(msgStream, msgLen);
|
||||
if (aMsgStream) {
|
||||
sent = mDataChannel->SendBinaryStream(aMsgStream, aMsgLength);
|
||||
} else {
|
||||
if (isBinary) {
|
||||
sent = mDataChannel->SendBinaryMsg(msgString);
|
||||
if (aIsBinary) {
|
||||
sent = mDataChannel->SendBinaryMsg(aMsgString);
|
||||
} else {
|
||||
sent = mDataChannel->SendMsg(msgString);
|
||||
sent = mDataChannel->SendMsg(aMsgString);
|
||||
}
|
||||
}
|
||||
return sent >= 0 ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// XXX Exact clone of nsWebSocketChannel::GetSendParams() - find a way to share!
|
||||
nsresult
|
||||
nsDOMDataChannel::GetSendParams(nsIVariant* aData, nsCString& aStringOut,
|
||||
nsCOMPtr<nsIInputStream>& aStreamOut,
|
||||
bool& aIsBinary, uint32_t& aOutgoingLength)
|
||||
{
|
||||
// Get type of data (arraybuffer, blob, or string)
|
||||
uint16_t dataType;
|
||||
nsresult rv = aData->GetDataType(&dataType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (dataType == nsIDataType::VTYPE_INTERFACE ||
|
||||
dataType == nsIDataType::VTYPE_INTERFACE_IS) {
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
nsID* iid;
|
||||
rv = aData->GetAsInterface(&iid, getter_AddRefs(supports));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsMemory::Free(iid);
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
// ArrayBuffer?
|
||||
JS::Rooted<JS::Value> realVal(cx);
|
||||
JS::Rooted<JSObject*> obj(cx);
|
||||
nsresult rv = aData->GetAsJSVal(realVal.address());
|
||||
if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(realVal) &&
|
||||
(obj = JSVAL_TO_OBJECT(realVal)) &&
|
||||
(JS_IsArrayBufferObject(obj))) {
|
||||
int32_t len = JS_GetArrayBufferByteLength(obj);
|
||||
char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(obj));
|
||||
|
||||
aStringOut.Assign(data, len);
|
||||
aIsBinary = true;
|
||||
aOutgoingLength = len;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Blob?
|
||||
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(supports);
|
||||
if (blob) {
|
||||
rv = blob->GetInternalStream(getter_AddRefs(aStreamOut));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// GetSize() should not perform blocking I/O (unlike Available())
|
||||
uint64_t blobLen;
|
||||
rv = blob->GetSize(&blobLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (blobLen > UINT32_MAX) {
|
||||
return NS_ERROR_FILE_TOO_BIG;
|
||||
}
|
||||
aOutgoingLength = static_cast<uint32_t>(blobLen);
|
||||
|
||||
aIsBinary = true;
|
||||
return NS_OK;
|
||||
}
|
||||
if (sent < 0) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
// Text message: if not already a string, turn it into one.
|
||||
// TODO: bug 704444: Correctly coerce any JS type to string
|
||||
//
|
||||
PRUnichar* data = nullptr;
|
||||
uint32_t len = 0;
|
||||
rv = aData->GetAsWStringWithSize(&len, &data);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsString text;
|
||||
text.Adopt(data, len);
|
||||
|
||||
CopyUTF16toUTF8(text, aStringOut);
|
||||
|
||||
aIsBinary = false;
|
||||
aOutgoingLength = aStringOut.Length();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -4,27 +4,107 @@
|
|||
* 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 nsDOMDataChannel_h__
|
||||
#define nsDOMDataChannel_h__
|
||||
#ifndef nsDOMDataChannel_h
|
||||
#define nsDOMDataChannel_h
|
||||
|
||||
// This defines only what's necessary to create nsDOMDataChannels, since this
|
||||
// gets used with MOZ_INTERNAL_API not set for media/webrtc/signaling/testing
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/dom/DataChannelBinding.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "mozilla/net/DataChannel.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsIDOMDataChannel.h"
|
||||
|
||||
namespace mozilla {
|
||||
class DataChannel;
|
||||
}
|
||||
class nsDOMDataChannel : public nsDOMEventTargetHelper,
|
||||
public nsIDOMDataChannel,
|
||||
public mozilla::DataChannelListener
|
||||
{
|
||||
public:
|
||||
nsDOMDataChannel(already_AddRefed<mozilla::DataChannel> aDataChannel)
|
||||
: mDataChannel(aDataChannel)
|
||||
, mBinaryType(DC_BINARY_TYPE_BLOB)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
class nsPIDOMWindow;
|
||||
~nsDOMDataChannel();
|
||||
|
||||
nsresult
|
||||
NS_NewDOMDataChannel(already_AddRefed<mozilla::DataChannel> dataChannel,
|
||||
nsPIDOMWindow* aWindow,
|
||||
nsIDOMDataChannel** domDataChannel);
|
||||
nsresult Init(nsPIDOMWindow* aDOMWindow);
|
||||
|
||||
// Tell DataChannel it's ok to deliver open and message events
|
||||
void NS_DataChannelAppReady(nsIDOMDataChannel* domDataChannel);
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDOMDATACHANNEL
|
||||
|
||||
#endif
|
||||
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMDataChannel,
|
||||
nsDOMEventTargetHelper)
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
MOZ_OVERRIDE;
|
||||
nsPIDOMWindow* GetParentObject() const
|
||||
{
|
||||
return GetOwner();
|
||||
}
|
||||
|
||||
// WebIDL
|
||||
// Uses XPIDL GetLabel.
|
||||
bool Reliable() const;
|
||||
mozilla::dom::RTCDataChannelState ReadyState() const;
|
||||
uint32_t BufferedAmount() const;
|
||||
IMPL_EVENT_HANDLER(open)
|
||||
IMPL_EVENT_HANDLER(error)
|
||||
IMPL_EVENT_HANDLER(close)
|
||||
// Uses XPIDL Close.
|
||||
IMPL_EVENT_HANDLER(message)
|
||||
mozilla::dom::RTCDataChannelType BinaryType() const
|
||||
{
|
||||
return static_cast<mozilla::dom::RTCDataChannelType>(
|
||||
static_cast<int>(mBinaryType));
|
||||
}
|
||||
void SetBinaryType(mozilla::dom::RTCDataChannelType aType)
|
||||
{
|
||||
mBinaryType = static_cast<DataChannelBinaryType>(
|
||||
static_cast<int>(aType));
|
||||
}
|
||||
void Send(const nsAString& aData, mozilla::ErrorResult& aRv);
|
||||
void Send(nsIDOMBlob* aData, mozilla::ErrorResult& aRv);
|
||||
void Send(mozilla::dom::ArrayBuffer& aData, mozilla::ErrorResult& aRv);
|
||||
void Send(mozilla::dom::ArrayBufferView& aData, mozilla::ErrorResult& aRv);
|
||||
|
||||
// Uses XPIDL GetProtocol.
|
||||
bool Ordered() const;
|
||||
uint16_t Stream() const;
|
||||
|
||||
nsresult
|
||||
DoOnMessageAvailable(const nsACString& aMessage, bool aBinary);
|
||||
|
||||
virtual nsresult
|
||||
OnMessageAvailable(nsISupports* aContext, const nsACString& aMessage);
|
||||
|
||||
virtual nsresult
|
||||
OnBinaryMessageAvailable(nsISupports* aContext, const nsACString& aMessage);
|
||||
|
||||
virtual nsresult OnSimpleEvent(nsISupports* aContext, const nsAString& aName);
|
||||
|
||||
virtual nsresult
|
||||
OnChannelConnected(nsISupports* aContext);
|
||||
|
||||
virtual nsresult
|
||||
OnChannelClosed(nsISupports* aContext);
|
||||
|
||||
virtual void
|
||||
AppReady();
|
||||
|
||||
private:
|
||||
void Send(nsIInputStream* aMsgStream, const nsACString& aMsgString,
|
||||
uint32_t aMsgLength, bool aIsBinary, mozilla::ErrorResult& aRv);
|
||||
|
||||
// Owning reference
|
||||
nsRefPtr<mozilla::DataChannel> mDataChannel;
|
||||
nsString mOrigin;
|
||||
enum DataChannelBinaryType {
|
||||
DC_BINARY_TYPE_ARRAYBUFFER,
|
||||
DC_BINARY_TYPE_BLOB,
|
||||
};
|
||||
DataChannelBinaryType mBinaryType;
|
||||
};
|
||||
|
||||
#endif // nsDOMDataChannel_h
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et 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 nsDOMDataChannelDeclarations_h
|
||||
#define nsDOMDataChannelDeclarations_h
|
||||
|
||||
// This defines only what's necessary to create nsDOMDataChannels, since this
|
||||
// gets used with MOZ_INTERNAL_API not set for media/webrtc/signaling/testing
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMDataChannel.h"
|
||||
|
||||
namespace mozilla {
|
||||
class DataChannel;
|
||||
}
|
||||
|
||||
class nsPIDOMWindow;
|
||||
|
||||
nsresult
|
||||
NS_NewDOMDataChannel(already_AddRefed<mozilla::DataChannel> dataChannel,
|
||||
nsPIDOMWindow* aWindow,
|
||||
nsIDOMDataChannel** domDataChannel);
|
||||
|
||||
// Tell DataChannel it's ok to deliver open and message events
|
||||
void NS_DataChannelAppReady(nsIDOMDataChannel* domDataChannel);
|
||||
|
||||
#endif // nsDOMDataChannelDeclarations_h
|
|
@ -165,7 +165,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsDOMEventTargetHelper,
|
|||
return GetEventHandler(nsGkAtoms::on##_event); \
|
||||
} \
|
||||
inline void SetOn##_event(mozilla::dom::EventHandlerNonNull* aCallback, \
|
||||
ErrorResult& aRv) \
|
||||
mozilla::ErrorResult& aRv) \
|
||||
{ \
|
||||
SetEventHandler(nsGkAtoms::on##_event, aCallback, aRv); \
|
||||
}
|
||||
|
|
|
@ -333,10 +333,6 @@ using mozilla::dom::workers::ResolveWorkerClasses;
|
|||
#include "TimeManager.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WEBRTC
|
||||
#include "nsIDOMDataChannel.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -904,11 +900,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
NS_DEFINE_CLASSINFO_DATA(MozTimeManager, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WEBRTC
|
||||
NS_DEFINE_CLASSINFO_DATA(DataChannel, nsEventTargetSH,
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
#endif
|
||||
};
|
||||
|
||||
#define NS_DEFINE_CONTRACT_CTOR(_class, _contract_id) \
|
||||
|
@ -2278,13 +2269,6 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_MAP_END
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WEBRTC
|
||||
DOM_CLASSINFO_MAP_BEGIN(DataChannel, nsIDOMDataChannel)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDataChannel)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
#endif
|
||||
|
||||
MOZ_STATIC_ASSERT(MOZ_ARRAY_LENGTH(sClassInfoData) == eDOMClassInfoIDCount,
|
||||
"The number of items in sClassInfoData doesn't match the "
|
||||
"number of nsIDOMClassInfo ID's, this is bad! Fix it!");
|
||||
|
|
|
@ -239,5 +239,4 @@ DOMCI_CLASS(MozTimeManager)
|
|||
#endif
|
||||
|
||||
#ifdef MOZ_WEBRTC
|
||||
DOMCI_CLASS(DataChannel)
|
||||
#endif
|
||||
|
|
|
@ -231,6 +231,10 @@ DOMInterfaces = {
|
|||
'nativeType': 'nsDOMCSSValueList'
|
||||
},
|
||||
|
||||
'DataChannel': {
|
||||
'nativeType': 'nsDOMDataChannel',
|
||||
},
|
||||
|
||||
'DataContainerEvent': {
|
||||
'nativeType': 'nsDOMDataContainerEvent',
|
||||
},
|
||||
|
|
|
@ -6057,7 +6057,7 @@ class ClassMethod(ClassItem):
|
|||
${className}::${name}(${args})${const}
|
||||
{
|
||||
${body}
|
||||
}\n
|
||||
}
|
||||
""").substitute({ 'templateClause': templateClause,
|
||||
'decorators': self.getDecorators(False),
|
||||
'returnType': self.returnType,
|
||||
|
@ -6096,7 +6096,7 @@ class ClassConstructor(ClassItem):
|
|||
self.inline = inline or bodyInHeader
|
||||
self.bodyInHeader = bodyInHeader
|
||||
self.explicit = explicit
|
||||
self.baseConstructors = baseConstructors
|
||||
self.baseConstructors = baseConstructors or []
|
||||
self.body = body
|
||||
ClassItem.__init__(self, None, visibility)
|
||||
|
||||
|
@ -6114,7 +6114,7 @@ class ClassConstructor(ClassItem):
|
|||
items = [str(c) for c in self.baseConstructors]
|
||||
for m in cgClass.members:
|
||||
if not m.static:
|
||||
initialize = m.getBody()
|
||||
initialize = m.body
|
||||
if initialize:
|
||||
items.append(m.name + "(" + initialize + ")")
|
||||
|
||||
|
@ -6155,7 +6155,7 @@ class ClassConstructor(ClassItem):
|
|||
|
||||
return string.Template("""${decorators}
|
||||
${className}::${className}(${args})${initializationList}
|
||||
{${body}}\n
|
||||
{${body}}
|
||||
""").substitute({ 'decorators': self.getDecorators(False),
|
||||
'className': cgClass.getNameString(),
|
||||
'args': args,
|
||||
|
@ -6225,7 +6225,7 @@ class ClassDestructor(ClassItem):
|
|||
|
||||
return string.Template("""${decorators}
|
||||
${className}::~${className}()
|
||||
{${body}}\n
|
||||
{${body}}
|
||||
""").substitute({ 'decorators': self.getDecorators(False),
|
||||
'className': cgClass.getNameString(),
|
||||
'body': body })
|
||||
|
@ -6289,7 +6289,8 @@ class CGClass(CGThing):
|
|||
def __init__(self, name, bases=[], members=[], constructors=[],
|
||||
destructor=None, methods=[],
|
||||
typedefs = [], enums=[], templateArgs=[],
|
||||
templateSpecialization=[], isStruct=False, indent='',
|
||||
templateSpecialization=[], isStruct=False,
|
||||
disallowCopyConstruction=False, indent='',
|
||||
decorators='',
|
||||
extradeclarations='',
|
||||
extradefinitions=''):
|
||||
|
@ -6307,6 +6308,7 @@ class CGClass(CGThing):
|
|||
self.templateArgs = templateArgs
|
||||
self.templateSpecialization = templateSpecialization
|
||||
self.isStruct = isStruct
|
||||
self.disallowCopyConstruction = disallowCopyConstruction
|
||||
self.indent = indent
|
||||
self.defaultVisibility ='public' if isStruct else 'private'
|
||||
self.decorators = decorators
|
||||
|
@ -6392,9 +6394,20 @@ class CGClass(CGThing):
|
|||
lastVisibility = visibility
|
||||
return (result, lastVisibility, itemCount)
|
||||
|
||||
if self.disallowCopyConstruction:
|
||||
class DisallowedCopyConstructor(object):
|
||||
def __init__(self):
|
||||
self.visibility = "private"
|
||||
def declare(self, cgClass):
|
||||
name = cgClass.getNameString()
|
||||
return "%s(const %s&) MOZ_DELETE;\n" % (name, name)
|
||||
disallowedCopyConstructors = [DisallowedCopyConstructor()]
|
||||
else:
|
||||
disallowedCopyConstructors = []
|
||||
|
||||
order = [(self.enums, ''), (self.typedefs, ''), (self.members, ''),
|
||||
(self.constructors, '\n'), (self.destructors, '\n'),
|
||||
(self.methods, '\n')]
|
||||
(self.constructors + disallowedCopyConstructors, '\n'),
|
||||
(self.destructors, '\n'), (self.methods, '\n')]
|
||||
|
||||
lastVisibility = self.defaultVisibility
|
||||
itemCount = 0
|
||||
|
@ -6416,11 +6429,14 @@ class CGClass(CGThing):
|
|||
for member in memberList:
|
||||
if itemCount != 0:
|
||||
result = result + separator
|
||||
result = result + member.define(cgClass)
|
||||
itemCount = itemCount + 1
|
||||
definition = member.define(cgClass)
|
||||
if definition:
|
||||
# Member variables would only produce empty lines here.
|
||||
result += definition
|
||||
itemCount += 1
|
||||
return (result, itemCount)
|
||||
|
||||
order = [(self.members, '\n'), (self.constructors, '\n'),
|
||||
order = [(self.members, ''), (self.constructors, '\n'),
|
||||
(self.destructors, '\n'), (self.methods, '\n')]
|
||||
|
||||
result = self.extradefinitions
|
||||
|
@ -7492,6 +7508,7 @@ class CGDictionary(CGThing):
|
|||
self.dictionary = dictionary
|
||||
self.descriptorProvider = descriptorProvider
|
||||
self.workers = descriptorProvider.workers
|
||||
# NOTE: jsids are per-runtime, so don't use them in workers
|
||||
self.needToInitIds = not self.workers and len(dictionary.members) > 0
|
||||
self.memberInfo = [
|
||||
(member,
|
||||
|
@ -7501,169 +7518,194 @@ class CGDictionary(CGThing):
|
|||
isOptional=(not member.defaultValue),
|
||||
defaultValue=member.defaultValue))
|
||||
for member in dictionary.members ]
|
||||
self.structs = self.getStructs()
|
||||
|
||||
def declare(self):
|
||||
d = self.dictionary
|
||||
if d.parent:
|
||||
inheritance = "%s" % self.makeClassName(d.parent)
|
||||
elif not self.workers:
|
||||
inheritance = "MainThreadDictionaryBase"
|
||||
else:
|
||||
inheritance = "DictionaryBase"
|
||||
memberDecls = [" %s %s;" %
|
||||
(self.getMemberType(m),
|
||||
self.makeMemberName(m[0].identifier.name))
|
||||
for m in self.memberInfo]
|
||||
|
||||
return (string.Template(
|
||||
"struct ${selfName} : public ${inheritance} {\n"
|
||||
" ${selfName}() {}\n"
|
||||
" bool Init(JSContext* cx, JS::Handle<JS::Value> val);\n" +
|
||||
(" bool Init(const nsAString& aJSON);\n" if not self.workers else "") +
|
||||
" bool ToObject(JSContext* cx, JS::Handle<JSObject*> parentObject, JS::Value *vp) const;\n"
|
||||
" void TraceDictionary(JSTracer* trc);\n"
|
||||
"\n" +
|
||||
"\n".join(memberDecls) + "\n"
|
||||
"private:\n"
|
||||
" // Disallow copy-construction\n"
|
||||
" ${selfName}(const ${selfName}&) MOZ_DELETE;\n" +
|
||||
# NOTE: jsids are per-runtime, so don't use them in workers
|
||||
(" static bool InitIds(JSContext* cx);\n"
|
||||
" static bool initedIds;\n" if self.needToInitIds else "") +
|
||||
"\n".join(" static jsid " +
|
||||
self.makeIdName(m.identifier.name) + ";" for
|
||||
m in d.members) + "\n"
|
||||
"};\n"
|
||||
"struct ${selfName}Initializer : public ${selfName} {\n"
|
||||
" ${selfName}Initializer() {\n"
|
||||
" // Safe to pass a null context if we pass a null value\n"
|
||||
" Init(nullptr, JS::NullHandleValue);\n"
|
||||
" }\n"
|
||||
"};").substitute( { "selfName": self.makeClassName(d),
|
||||
"inheritance": inheritance }))
|
||||
return self.structs.declare()
|
||||
|
||||
def define(self):
|
||||
d = self.dictionary
|
||||
if d.parent:
|
||||
initParent = ("// Per spec, we init the parent's members first\n"
|
||||
"if (!%s::Init(cx, val)) {\n"
|
||||
" return false;\n"
|
||||
"}\n" % self.makeClassName(d.parent))
|
||||
toObjectParent = ("// Per spec, we define the parent's members first\n"
|
||||
"if (!%s::ToObject(cx, parentObject, vp)) {\n"
|
||||
" return false;\n"
|
||||
"}\n" % self.makeClassName(d.parent))
|
||||
ensureObject = "JS::Rooted<JSObject*> obj(cx, &vp->toObject());\n"
|
||||
traceParent = ("%s::TraceDictionary(trc);\n" %
|
||||
self.makeClassName(d.parent))
|
||||
else:
|
||||
initParent = ""
|
||||
toObjectParent = ""
|
||||
ensureObject = ("JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));\n"
|
||||
"if (!obj) {\n"
|
||||
" return false;\n"
|
||||
"}\n"
|
||||
"*vp = JS::ObjectValue(*obj);\n")
|
||||
traceParent = ""
|
||||
return self.structs.define()
|
||||
|
||||
memberInits = [CGIndenter(self.getMemberConversion(m)).define()
|
||||
def base(self):
|
||||
if self.dictionary.parent:
|
||||
return self.makeClassName(self.dictionary.parent)
|
||||
if not self.workers:
|
||||
return "MainThreadDictionaryBase"
|
||||
return "DictionaryBase"
|
||||
|
||||
def initMethod(self):
|
||||
body = (
|
||||
"// Passing a null JSContext is OK only if we're initing from null,\n"
|
||||
"// Since in that case we will not have to do any property gets\n"
|
||||
"MOZ_ASSERT_IF(!cx, val.isNull());\n")
|
||||
|
||||
if self.needToInitIds:
|
||||
body += (
|
||||
"if (cx && !initedIds && !InitIds(cx)) {\n"
|
||||
" return false;\n"
|
||||
"}\n")
|
||||
|
||||
if self.dictionary.parent:
|
||||
body += (
|
||||
"// Per spec, we init the parent's members first\n"
|
||||
"if (!%s::Init(cx, val)) {\n"
|
||||
" return false;\n"
|
||||
"}\n") % self.makeClassName(self.dictionary.parent)
|
||||
|
||||
memberInits = [self.getMemberConversion(m).define()
|
||||
for m in self.memberInfo]
|
||||
if memberInits:
|
||||
body += (
|
||||
"JSBool found;\n"
|
||||
"JS::Rooted<JS::Value> temp(cx);\n"
|
||||
"bool isNull = val.isNullOrUndefined();\n")
|
||||
|
||||
body += (
|
||||
"if (!IsConvertibleToDictionary(cx, val)) {\n"
|
||||
" return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY);\n"
|
||||
"}\n"
|
||||
"\n")
|
||||
|
||||
if memberInits:
|
||||
body += "\n\n".join(memberInits) + "\n"
|
||||
|
||||
body += "return true;"
|
||||
|
||||
return ClassMethod("Init", "bool", [
|
||||
Argument('JSContext*', 'cx'),
|
||||
Argument('JS::Handle<JS::Value>', 'val'),
|
||||
], body=body)
|
||||
|
||||
def initFromJSONMethod(self):
|
||||
assert not self.workers
|
||||
return ClassMethod("Init", "bool", [
|
||||
Argument('const nsAString&', 'aJSON'),
|
||||
], body=(
|
||||
"AutoSafeJSContext cx;\n"
|
||||
"JSAutoRequest ar(cx);\n"
|
||||
"JS::Rooted<JS::Value> json(cx);\n"
|
||||
"bool ok = ParseJSON(cx, aJSON, &json);\n"
|
||||
"NS_ENSURE_TRUE(ok, false);\n"
|
||||
"return Init(cx, json);"
|
||||
))
|
||||
|
||||
def toObjectMethod(self):
|
||||
body = ""
|
||||
if self.needToInitIds:
|
||||
body += (
|
||||
"if (!initedIds && !InitIds(cx)) {\n"
|
||||
" return false;\n"
|
||||
"}\n")
|
||||
|
||||
if self.dictionary.parent:
|
||||
body += (
|
||||
"// Per spec, we define the parent's members first\n"
|
||||
"if (!%s::ToObject(cx, parentObject, vp)) {\n"
|
||||
" return false;\n"
|
||||
"}\n"
|
||||
"JS::Rooted<JSObject*> obj(cx, &vp->toObject());\n"
|
||||
"\n") % self.makeClassName(self.dictionary.parent)
|
||||
else:
|
||||
body += (
|
||||
"JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));\n"
|
||||
"if (!obj) {\n"
|
||||
" return false;\n"
|
||||
"}\n"
|
||||
"*vp = JS::ObjectValue(*obj);\n"
|
||||
"\n")
|
||||
|
||||
body += "\n\n".join(self.getMemberDefinition(m).define()
|
||||
for m in self.memberInfo)
|
||||
body += "\n\nreturn true;"
|
||||
|
||||
return ClassMethod("ToObject", "bool", [
|
||||
Argument('JSContext*', 'cx'),
|
||||
Argument('JS::Handle<JSObject*>', 'parentObject'),
|
||||
Argument('JS::Value*', 'vp'),
|
||||
], const=True, body=body)
|
||||
|
||||
def initIdsMethod(self):
|
||||
assert self.needToInitIds
|
||||
idinit = [CGGeneric('!InternJSString(cx, %s, "%s")' %
|
||||
(m.identifier.name + "_id", m.identifier.name))
|
||||
for m in d.members]
|
||||
for m in self.dictionary.members]
|
||||
idinit = CGList(idinit, " ||\n")
|
||||
idinit = CGWrapper(idinit, pre="if (",
|
||||
post=(") {\n"
|
||||
" return false;\n"
|
||||
"}"),
|
||||
reindent=True)
|
||||
memberDefines = [CGIndenter(self.getMemberDefinition(m)).define()
|
||||
for m in self.memberInfo]
|
||||
memberTraces = [CGIndenter(self.getMemberTrace(m)).define()
|
||||
body = (
|
||||
"MOZ_ASSERT(!initedIds);\n"
|
||||
"%s\n"
|
||||
"initedIds = true;\n"
|
||||
"return true;") % idinit.define()
|
||||
|
||||
return ClassMethod("InitIds", "bool", [
|
||||
Argument("JSContext*", "cx"),
|
||||
], static=True, body=body, visibility="private")
|
||||
|
||||
def traceDictionaryMethod(self):
|
||||
body = ""
|
||||
if self.dictionary.parent:
|
||||
cls = self.makeClassName(self.dictionary.parent)
|
||||
body += "%s::TraceDictionary(trc);\n" % cls
|
||||
|
||||
memberTraces = [self.getMemberTrace(m)
|
||||
for m in self.dictionary.members
|
||||
if typeNeedsCx(m.type, self.descriptorProvider)]
|
||||
|
||||
return string.Template(
|
||||
# NOTE: jsids are per-runtime, so don't use them in workers
|
||||
("bool ${selfName}::initedIds = false;\n" +
|
||||
"\n".join("jsid ${selfName}::%s = JSID_VOID;" %
|
||||
self.makeIdName(m.identifier.name)
|
||||
for m in d.members) + "\n"
|
||||
"\n"
|
||||
"bool\n"
|
||||
"${selfName}::InitIds(JSContext* cx)\n"
|
||||
"{\n"
|
||||
" MOZ_ASSERT(!initedIds);\n"
|
||||
"${idInit}\n"
|
||||
" initedIds = true;\n"
|
||||
" return true;\n"
|
||||
"}\n"
|
||||
"\n" if self.needToInitIds else "") +
|
||||
"bool\n"
|
||||
"${selfName}::Init(JSContext* cx, JS::Handle<JS::Value> val)\n"
|
||||
"{\n"
|
||||
" // Passing a null JSContext is OK only if we're initing from null,\n"
|
||||
" // Since in that case we will not have to do any property gets\n"
|
||||
" MOZ_ASSERT_IF(!cx, val.isNull());\n" +
|
||||
# NOTE: jsids are per-runtime, so don't use them in workers
|
||||
(" if (cx && !initedIds && !InitIds(cx)) {\n"
|
||||
" return false;\n"
|
||||
" }\n" if self.needToInitIds else "") +
|
||||
"${initParent}" +
|
||||
(" JSBool found;\n"
|
||||
" JS::Rooted<JS::Value> temp(cx);\n"
|
||||
" bool isNull = val.isNullOrUndefined();\n" if len(memberInits) > 0 else "") +
|
||||
" if (!IsConvertibleToDictionary(cx, val)) {\n"
|
||||
" return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY);\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
"${initMembers}\n"
|
||||
" return true;\n"
|
||||
"}\n"
|
||||
"\n" +
|
||||
("bool\n"
|
||||
"${selfName}::Init(const nsAString& aJSON)\n"
|
||||
"{\n"
|
||||
" AutoSafeJSContext cx;\n"
|
||||
" JSAutoRequest ar(cx);\n"
|
||||
" JS::Rooted<JS::Value> json(cx);\n"
|
||||
" bool ok = ParseJSON(cx, aJSON, &json);\n"
|
||||
" NS_ENSURE_TRUE(ok, false);\n"
|
||||
" return Init(cx, json);\n"
|
||||
"}\n" if not self.workers else "") +
|
||||
"\n"
|
||||
"bool\n"
|
||||
"${selfName}::ToObject(JSContext* cx, JS::Handle<JSObject*> parentObject, JS::Value *vp) const\n"
|
||||
"{\n" +
|
||||
# NOTE: jsids are per-runtime, so don't use them in workers
|
||||
(" if (!initedIds && !InitIds(cx)) {\n"
|
||||
" return false;\n"
|
||||
" }\n" if self.needToInitIds else "") +
|
||||
"${toObjectParent}"
|
||||
"${ensureObject}"
|
||||
"\n"
|
||||
"${defineMembers}\n"
|
||||
"\n"
|
||||
" return true;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void\n"
|
||||
"${selfName}::TraceDictionary(JSTracer* trc)\n"
|
||||
"{\n"
|
||||
"${traceParent}"
|
||||
"${traceMembers}\n"
|
||||
"}").substitute({
|
||||
"selfName": self.makeClassName(d),
|
||||
"initParent": CGIndenter(CGGeneric(initParent)).define(),
|
||||
"initMembers": "\n\n".join(memberInits),
|
||||
"idInit": CGIndenter(idinit).define(),
|
||||
"isMainThread": toStringBool(not self.workers),
|
||||
"toObjectParent": CGIndenter(CGGeneric(toObjectParent)).define(),
|
||||
"ensureObject": CGIndenter(CGGeneric(ensureObject)).define(),
|
||||
"traceMembers": "\n\n".join(memberTraces),
|
||||
"traceParent": CGIndenter(CGGeneric(traceParent)).define(),
|
||||
"defineMembers": "\n\n".join(memberDefines)
|
||||
})
|
||||
body += "\n\n".join(memberTraces)
|
||||
|
||||
return ClassMethod("TraceDictionary", "void", [
|
||||
Argument("JSTracer*", "trc"),
|
||||
], body=body)
|
||||
|
||||
def getStructs(self):
|
||||
d = self.dictionary
|
||||
selfName = self.makeClassName(d)
|
||||
members = [ClassMember(self.makeMemberName(m[0].identifier.name),
|
||||
self.getMemberType(m),
|
||||
visibility="public") for m in self.memberInfo]
|
||||
ctor = ClassConstructor([], bodyInHeader=True, visibility="public")
|
||||
methods = []
|
||||
|
||||
if self.needToInitIds:
|
||||
methods.append(self.initIdsMethod())
|
||||
members.append(ClassMember("initedIds", "bool", static=True, body="false"))
|
||||
members.extend(
|
||||
ClassMember(self.makeIdName(m.identifier.name), "jsid", static=True, body="JSID_VOID")
|
||||
for m in d.members)
|
||||
|
||||
methods.append(self.initMethod())
|
||||
|
||||
if not self.workers:
|
||||
methods.append(self.initFromJSONMethod())
|
||||
|
||||
methods.append(self.toObjectMethod())
|
||||
methods.append(self.traceDictionaryMethod())
|
||||
|
||||
struct = CGClass(selfName,
|
||||
bases=[ClassBase(self.base())],
|
||||
members=members,
|
||||
constructors=[ctor],
|
||||
methods=methods,
|
||||
isStruct=True,
|
||||
disallowCopyConstruction=True)
|
||||
|
||||
|
||||
initializerCtor = ClassConstructor([],
|
||||
bodyInHeader=True,
|
||||
visibility="public",
|
||||
body=(
|
||||
"// Safe to pass a null context if we pass a null value\n"
|
||||
"Init(nullptr, JS::NullHandleValue);"))
|
||||
initializerStruct = CGClass(selfName + "Initializer",
|
||||
bases=[ClassBase(selfName)],
|
||||
constructors=[initializerCtor],
|
||||
isStruct=True)
|
||||
|
||||
return CGList([struct, initializerStruct])
|
||||
|
||||
def deps(self):
|
||||
return self.dictionary.getDeps()
|
||||
|
@ -7843,7 +7885,7 @@ class CGDictionary(CGThing):
|
|||
if not member.defaultValue:
|
||||
trace = CGIfWrapper(trace, "%s.WasPassed()" % memberLoc)
|
||||
|
||||
return trace
|
||||
return trace.define()
|
||||
|
||||
@staticmethod
|
||||
def makeIdName(name):
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/* 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/. */
|
||||
|
||||
enum RTCDataChannelState {
|
||||
"connecting",
|
||||
"open",
|
||||
"closing",
|
||||
"closed"
|
||||
};
|
||||
|
||||
enum RTCDataChannelType {
|
||||
"arraybuffer",
|
||||
"blob"
|
||||
};
|
||||
|
||||
// XXX This interface is called RTCDataChannel in the spec.
|
||||
interface DataChannel : EventTarget
|
||||
{
|
||||
readonly attribute DOMString label;
|
||||
readonly attribute boolean reliable;
|
||||
readonly attribute RTCDataChannelState readyState;
|
||||
readonly attribute unsigned long bufferedAmount;
|
||||
[SetterThrows]
|
||||
attribute EventHandler onopen;
|
||||
[SetterThrows]
|
||||
attribute EventHandler onerror;
|
||||
[SetterThrows]
|
||||
attribute EventHandler onclose;
|
||||
void close();
|
||||
[SetterThrows]
|
||||
attribute EventHandler onmessage;
|
||||
attribute RTCDataChannelType binaryType;
|
||||
[Throws]
|
||||
void send(DOMString data);
|
||||
[Throws]
|
||||
void send(Blob data);
|
||||
[Throws]
|
||||
void send(ArrayBuffer data);
|
||||
[Throws]
|
||||
void send(ArrayBufferView data);
|
||||
};
|
||||
|
||||
// Mozilla extensions.
|
||||
partial interface DataChannel
|
||||
{
|
||||
readonly attribute DOMString protocol;
|
||||
readonly attribute boolean ordered;
|
||||
readonly attribute unsigned short stream;
|
||||
};
|
|
@ -359,6 +359,7 @@ endif
|
|||
|
||||
ifdef MOZ_WEBRTC
|
||||
webidl_files += \
|
||||
DataChannel.webidl \
|
||||
MediaStreamList.webidl \
|
||||
$(NULL)
|
||||
endif
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "PeerConnectionCtx.h"
|
||||
#include "PeerConnectionImpl.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsDOMDataChannel.h"
|
||||
#include "nsDOMDataChannelDeclarations.h"
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
#include "nsContentUtils.h"
|
||||
|
|
|
@ -410,7 +410,7 @@ public:
|
|||
|
||||
void GetLabel(nsAString& aLabel) { CopyUTF8toUTF16(mLabel, aLabel); }
|
||||
void GetProtocol(nsAString& aProtocol) { CopyUTF8toUTF16(mProtocol, aProtocol); }
|
||||
void GetStream(uint16_t *aStream) { *aStream = mStream; }
|
||||
uint16_t GetStream() { return mStream; }
|
||||
|
||||
void AppReady();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче