This commit is contained in:
Ryan VanderMeulen 2013-05-20 08:02:31 -04:00
Родитель 4577814c24 b32d97ae67
Коммит 4f23c7f5c8
14 изменённых файлов: 531 добавлений и 381 удалений

Просмотреть файл

@ -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();