mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
WebRTCDataChannel initial support
This commit is contained in:
parent
5788882b16
commit
4e6d3e7cec
6 changed files with 335 additions and 1 deletions
|
@ -128,7 +128,7 @@ use servo_media::player::video::VideoFrame;
|
||||||
use servo_media::player::Player;
|
use servo_media::player::Player;
|
||||||
use servo_media::streams::registry::MediaStreamId;
|
use servo_media::streams::registry::MediaStreamId;
|
||||||
use servo_media::streams::MediaStreamType;
|
use servo_media::streams::MediaStreamType;
|
||||||
use servo_media::webrtc::WebRtcController;
|
use servo_media::webrtc::{WebRtcController, WebRtcDataChannelBackend};
|
||||||
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
|
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -607,6 +607,7 @@ unsafe_no_jsmanaged_fields!(NodeId);
|
||||||
unsafe_no_jsmanaged_fields!(AnalysisEngine, DistanceModel, PanningModel, ParamType);
|
unsafe_no_jsmanaged_fields!(AnalysisEngine, DistanceModel, PanningModel, ParamType);
|
||||||
unsafe_no_jsmanaged_fields!(Arc<Mutex<dyn Player>>);
|
unsafe_no_jsmanaged_fields!(Arc<Mutex<dyn Player>>);
|
||||||
unsafe_no_jsmanaged_fields!(WebRtcController);
|
unsafe_no_jsmanaged_fields!(WebRtcController);
|
||||||
|
unsafe_no_jsmanaged_fields!(Box<dyn WebRtcDataChannelBackend>);
|
||||||
unsafe_no_jsmanaged_fields!(MediaStreamId, MediaStreamType);
|
unsafe_no_jsmanaged_fields!(MediaStreamId, MediaStreamType);
|
||||||
unsafe_no_jsmanaged_fields!(Mutex<MediaFrameRenderer>);
|
unsafe_no_jsmanaged_fields!(Mutex<MediaFrameRenderer>);
|
||||||
unsafe_no_jsmanaged_fields!(ResourceFetchTiming);
|
unsafe_no_jsmanaged_fields!(ResourceFetchTiming);
|
||||||
|
|
|
@ -486,6 +486,7 @@ pub mod raredata;
|
||||||
pub mod readablestream;
|
pub mod readablestream;
|
||||||
pub mod request;
|
pub mod request;
|
||||||
pub mod response;
|
pub mod response;
|
||||||
|
pub mod rtcdatachannel;
|
||||||
pub mod rtcicecandidate;
|
pub mod rtcicecandidate;
|
||||||
pub mod rtcpeerconnection;
|
pub mod rtcpeerconnection;
|
||||||
pub mod rtcpeerconnectioniceevent;
|
pub mod rtcpeerconnectioniceevent;
|
||||||
|
|
260
components/script/dom/rtcdatachannel.rs
Normal file
260
components/script/dom/rtcdatachannel.rs
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
/* 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 https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::RTCDataChannelBinding::RTCDataChannelInit;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::RTCDataChannelBinding::RTCDataChannelMethods;
|
||||||
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
|
use crate::dom::bindings::refcounted::Trusted;
|
||||||
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::bindings::str::USVString;
|
||||||
|
use crate::dom::blob::Blob;
|
||||||
|
use crate::dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
|
use crate::dom::eventtarget::EventTarget;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::task_source::TaskSource;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
use js::rust::CustomAutoRooterGuard;
|
||||||
|
use js::typedarray::{ArrayBuffer, ArrayBufferView};
|
||||||
|
use servo_media::webrtc::{
|
||||||
|
WebRtcController, WebRtcDataChannelBackend, WebRtcDataChannelInit, WebRtcError,
|
||||||
|
};
|
||||||
|
use std::sync::mpsc;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct RTCDataChannel {
|
||||||
|
eventtarget: EventTarget,
|
||||||
|
#[ignore_malloc_size_of = "defined in servo-media"]
|
||||||
|
channel: Box<dyn WebRtcDataChannelBackend>,
|
||||||
|
label: USVString,
|
||||||
|
ordered: bool,
|
||||||
|
max_packet_life_time: Option<u16>,
|
||||||
|
max_retransmits: Option<u16>,
|
||||||
|
protocol: USVString,
|
||||||
|
negotiated: bool,
|
||||||
|
id: Option<u16>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RTCDataChannel {
|
||||||
|
#[allow(unrooted_must_root)]
|
||||||
|
pub fn new_inherited(
|
||||||
|
webrtc_controller: &DomRefCell<Option<WebRtcController>>,
|
||||||
|
label: USVString,
|
||||||
|
options: &RTCDataChannelInit,
|
||||||
|
) -> RTCDataChannel {
|
||||||
|
let webrtc = webrtc_controller.borrow();
|
||||||
|
let webrtc = webrtc.as_ref().unwrap();
|
||||||
|
|
||||||
|
let (sender, receiver) = mpsc::channel::<Box<dyn WebRtcDataChannelBackend>>();
|
||||||
|
|
||||||
|
let mut init: WebRtcDataChannelInit = options.into();
|
||||||
|
init.label = label.to_string();
|
||||||
|
|
||||||
|
webrtc.create_data_channel(init, sender);
|
||||||
|
let channel = receiver.recv().unwrap();
|
||||||
|
|
||||||
|
let rtc_data_channel = RTCDataChannel {
|
||||||
|
eventtarget: EventTarget::new_inherited(),
|
||||||
|
channel,
|
||||||
|
label,
|
||||||
|
ordered: options.ordered,
|
||||||
|
max_packet_life_time: options.maxPacketLifeTime,
|
||||||
|
max_retransmits: options.maxRetransmits,
|
||||||
|
protocol: options.protocol.clone(),
|
||||||
|
negotiated: options.negotiated,
|
||||||
|
id: options.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
let trusted = Trusted::new(&rtc_data_channel);
|
||||||
|
|
||||||
|
let this = trusted.clone();
|
||||||
|
rtc_data_channel.channel.set_on_open(Box::new(move || {
|
||||||
|
let this_ = this.clone();
|
||||||
|
let global = this.root().global();
|
||||||
|
let task_source = global.networking_task_source();
|
||||||
|
let _ = task_source.queue(
|
||||||
|
task!(on_open: move || {
|
||||||
|
this_.root().on_open();
|
||||||
|
}),
|
||||||
|
global.upcast(),
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
|
||||||
|
let this = trusted.clone();
|
||||||
|
rtc_data_channel.channel.set_on_close(Box::new(move || {
|
||||||
|
let this_ = this.clone();
|
||||||
|
let global = this.root().global();
|
||||||
|
let task_source = global.networking_task_source();
|
||||||
|
let _ = task_source.queue(
|
||||||
|
task!(on_close: move || {
|
||||||
|
this_.root().on_close();
|
||||||
|
}),
|
||||||
|
global.upcast(),
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
|
||||||
|
let this = trusted.clone();
|
||||||
|
rtc_data_channel
|
||||||
|
.channel
|
||||||
|
.set_on_error(Box::new(move |error| {
|
||||||
|
let this_ = this.clone();
|
||||||
|
let global = this.root().global();
|
||||||
|
let task_source = global.networking_task_source();
|
||||||
|
let _ = task_source.queue(
|
||||||
|
task!(on_error: move || {
|
||||||
|
this_.root().on_error(error);
|
||||||
|
}),
|
||||||
|
global.upcast(),
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
|
||||||
|
let this = trusted.clone();
|
||||||
|
rtc_data_channel
|
||||||
|
.channel
|
||||||
|
.set_on_message(Box::new(move |message| {
|
||||||
|
let this_ = this.clone();
|
||||||
|
let global = this.root().global();
|
||||||
|
let task_source = global.networking_task_source();
|
||||||
|
let _ = task_source.queue(
|
||||||
|
task!(on_message: move || {
|
||||||
|
this_.root().on_message(message);
|
||||||
|
}),
|
||||||
|
global.upcast(),
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
|
||||||
|
rtc_data_channel
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
global: &GlobalScope,
|
||||||
|
webrtc_controller: &DomRefCell<Option<WebRtcController>>,
|
||||||
|
label: USVString,
|
||||||
|
options: &RTCDataChannelInit,
|
||||||
|
) -> DomRoot<RTCDataChannel> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(RTCDataChannel::new_inherited(
|
||||||
|
webrtc_controller,
|
||||||
|
label,
|
||||||
|
options,
|
||||||
|
)),
|
||||||
|
global,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_open(&self) {
|
||||||
|
let event = Event::new(
|
||||||
|
&self.global(),
|
||||||
|
atom!("open"),
|
||||||
|
EventBubbles::DoesNotBubble,
|
||||||
|
EventCancelable::NotCancelable,
|
||||||
|
);
|
||||||
|
event.upcast::<Event>().fire(self.upcast());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_close(&self) {
|
||||||
|
let event = Event::new(
|
||||||
|
&self.global(),
|
||||||
|
atom!("close"),
|
||||||
|
EventBubbles::DoesNotBubble,
|
||||||
|
EventCancelable::NotCancelable,
|
||||||
|
);
|
||||||
|
event.upcast::<Event>().fire(self.upcast());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_error(&self, error: WebRtcError) {}
|
||||||
|
|
||||||
|
fn on_message(&self, message: String) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RTCDataChannelMethods for RTCDataChannel {
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-onopen
|
||||||
|
event_handler!(open, GetOnopen, SetOnopen);
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-onbufferedamountlow
|
||||||
|
event_handler!(
|
||||||
|
bufferedamountlow,
|
||||||
|
GetOnbufferedamountlow,
|
||||||
|
SetOnbufferedamountlow
|
||||||
|
);
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-onerror
|
||||||
|
event_handler!(error, GetOnerror, SetOnerror);
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-onclosing
|
||||||
|
event_handler!(closing, GetOnclosing, SetOnclosing);
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-onclose
|
||||||
|
event_handler!(close, GetOnclose, SetOnclose);
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-onmessage
|
||||||
|
event_handler!(message, GetOnmessage, SetOnmessage);
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-datachannel-label
|
||||||
|
fn Label(&self) -> USVString {
|
||||||
|
self.label.clone()
|
||||||
|
}
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-datachannel-ordered
|
||||||
|
fn Ordered(&self) -> bool {
|
||||||
|
self.ordered
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-datachannel-maxpacketlifetime
|
||||||
|
fn GetMaxPacketLifeTime(&self) -> Option<u16> {
|
||||||
|
self.max_packet_life_time
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-datachannel-maxretransmits
|
||||||
|
fn GetMaxRetransmits(&self) -> Option<u16> {
|
||||||
|
self.max_retransmits
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-datachannel-protocol
|
||||||
|
fn Protocol(&self) -> USVString {
|
||||||
|
self.protocol.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-datachannel-negotiated
|
||||||
|
fn Negotiated(&self) -> bool {
|
||||||
|
self.negotiated
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-id
|
||||||
|
fn GetId(&self) -> Option<u16> {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn ReadyState(&self) -> RTCDataChannelState;
|
||||||
|
// fn BufferedAmount(&self) -> u32;
|
||||||
|
// fn BufferedAmountLowThreshold(&self) -> u32;
|
||||||
|
// fn SetBufferedAmountLowThreshold(&self, value: u32) -> ();
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-close
|
||||||
|
fn Close(&self) -> () {}
|
||||||
|
|
||||||
|
// fn BinaryType(&self) -> DOMString;
|
||||||
|
// fn SetBinaryType(&self, value: DOMString) -> ();
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-send
|
||||||
|
fn Send(&self, data: USVString) -> () {}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-send!overload-1
|
||||||
|
fn Send_(&self, data: &Blob) -> () {}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-send!overload-2
|
||||||
|
fn Send__(&self, data: CustomAutoRooterGuard<ArrayBuffer>) -> () {}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-send!overload-3
|
||||||
|
fn Send___(&self, data: CustomAutoRooterGuard<ArrayBufferView>) -> () {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&RTCDataChannelInit> for WebRtcDataChannelInit {
|
||||||
|
fn from(init: &RTCDataChannelInit) -> WebRtcDataChannelInit {
|
||||||
|
WebRtcDataChannelInit {
|
||||||
|
label: String::new(),
|
||||||
|
id: init.id,
|
||||||
|
max_packet_life_time: init.maxPacketLifeTime,
|
||||||
|
max_retransmits: init.maxRetransmits,
|
||||||
|
negotiated: init.negotiated,
|
||||||
|
ordered: init.ordered,
|
||||||
|
protocol: init.protocol.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use crate::dom::bindings::cell::DomRefCell;
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::RTCDataChannelBinding::RTCDataChannelInit;
|
||||||
use crate::dom::bindings::codegen::Bindings::RTCIceCandidateBinding::RTCIceCandidateInit;
|
use crate::dom::bindings::codegen::Bindings::RTCIceCandidateBinding::RTCIceCandidateInit;
|
||||||
use crate::dom::bindings::codegen::Bindings::RTCPeerConnectionBinding::RTCPeerConnectionMethods;
|
use crate::dom::bindings::codegen::Bindings::RTCPeerConnectionBinding::RTCPeerConnectionMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::RTCPeerConnectionBinding::{
|
use crate::dom::bindings::codegen::Bindings::RTCPeerConnectionBinding::{
|
||||||
|
@ -20,12 +21,14 @@ use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
|
||||||
use crate::dom::bindings::reflector::reflect_dom_object;
|
use crate::dom::bindings::reflector::reflect_dom_object;
|
||||||
use crate::dom::bindings::reflector::DomObject;
|
use crate::dom::bindings::reflector::DomObject;
|
||||||
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
|
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
|
||||||
|
use crate::dom::bindings::str::USVString;
|
||||||
use crate::dom::event::{Event, EventBubbles, EventCancelable};
|
use crate::dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::mediastream::MediaStream;
|
use crate::dom::mediastream::MediaStream;
|
||||||
use crate::dom::mediastreamtrack::MediaStreamTrack;
|
use crate::dom::mediastreamtrack::MediaStreamTrack;
|
||||||
use crate::dom::promise::Promise;
|
use crate::dom::promise::Promise;
|
||||||
|
use crate::dom::rtcdatachannel::RTCDataChannel;
|
||||||
use crate::dom::rtcicecandidate::RTCIceCandidate;
|
use crate::dom::rtcicecandidate::RTCIceCandidate;
|
||||||
use crate::dom::rtcpeerconnectioniceevent::RTCPeerConnectionIceEvent;
|
use crate::dom::rtcpeerconnectioniceevent::RTCPeerConnectionIceEvent;
|
||||||
use crate::dom::rtcsessiondescription::RTCSessionDescription;
|
use crate::dom::rtcsessiondescription::RTCSessionDescription;
|
||||||
|
@ -448,6 +451,9 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
|
||||||
SetOnsignalingstatechange
|
SetOnsignalingstatechange
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-ondatachannel
|
||||||
|
event_handler!(datachannel, GetOndatachannel, SetOndatachannel);
|
||||||
|
|
||||||
/// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addicecandidate
|
/// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addicecandidate
|
||||||
fn AddIceCandidate(&self, candidate: &RTCIceCandidateInit, comp: InRealm) -> Rc<Promise> {
|
fn AddIceCandidate(&self, candidate: &RTCIceCandidateInit, comp: InRealm) -> Rc<Promise> {
|
||||||
let p = Promise::new_in_current_realm(&self.global(), comp);
|
let p = Promise::new_in_current_realm(&self.global(), comp);
|
||||||
|
@ -633,6 +639,15 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
|
||||||
// Step 11
|
// Step 11
|
||||||
// (no current support for connection state)
|
// (no current support for connection state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://www.w3.org/TR/webrtc/#dom-peerconnection-createdatachannel
|
||||||
|
fn CreateDataChannel(
|
||||||
|
&self,
|
||||||
|
label: USVString,
|
||||||
|
dataChannelDict: &RTCDataChannelInit,
|
||||||
|
) -> DomRoot<RTCDataChannel> {
|
||||||
|
RTCDataChannel::new(&self.global(), &self.controller, label, dataChannelDict)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SessionDescription> for RTCSessionDescriptionInit {
|
impl From<SessionDescription> for RTCSessionDescriptionInit {
|
||||||
|
|
49
components/script/dom/webidls/RTCDataChannel.webidl
Normal file
49
components/script/dom/webidls/RTCDataChannel.webidl
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/* 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 https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannel
|
||||||
|
|
||||||
|
[Exposed=Window]
|
||||||
|
interface RTCDataChannel : EventTarget {
|
||||||
|
readonly attribute USVString label;
|
||||||
|
readonly attribute boolean ordered;
|
||||||
|
readonly attribute unsigned short? maxPacketLifeTime;
|
||||||
|
readonly attribute unsigned short? maxRetransmits;
|
||||||
|
readonly attribute USVString protocol;
|
||||||
|
readonly attribute boolean negotiated;
|
||||||
|
readonly attribute unsigned short? id;
|
||||||
|
//readonly attribute RTCDataChannelState readyState;
|
||||||
|
//readonly attribute unsigned long bufferedAmount;
|
||||||
|
//attribute unsigned long bufferedAmountLowThreshold;
|
||||||
|
attribute EventHandler onopen;
|
||||||
|
attribute EventHandler onbufferedamountlow;
|
||||||
|
attribute EventHandler onerror;
|
||||||
|
attribute EventHandler onclosing;
|
||||||
|
attribute EventHandler onclose;
|
||||||
|
void close();
|
||||||
|
attribute EventHandler onmessage;
|
||||||
|
//attribute DOMString binaryType;
|
||||||
|
void send(USVString data);
|
||||||
|
void send(Blob data);
|
||||||
|
void send(ArrayBuffer data);
|
||||||
|
void send(ArrayBufferView data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannelinit
|
||||||
|
dictionary RTCDataChannelInit {
|
||||||
|
boolean ordered = true;
|
||||||
|
unsigned short maxPacketLifeTime;
|
||||||
|
unsigned short maxRetransmits;
|
||||||
|
USVString protocol = "";
|
||||||
|
boolean negotiated = false;
|
||||||
|
unsigned short id;
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#dom-rtcdatachannelstate
|
||||||
|
enum RTCDataChannelState {
|
||||||
|
"connecting",
|
||||||
|
"open",
|
||||||
|
"closing",
|
||||||
|
"closed"
|
||||||
|
};
|
|
@ -126,3 +126,11 @@ partial interface RTCPeerConnection {
|
||||||
// optional RTCRtpTransceiverInit init);
|
// optional RTCRtpTransceiverInit init);
|
||||||
attribute EventHandler ontrack;
|
attribute EventHandler ontrack;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webrtc/#rtcpeerconnection-interface-extensions-0
|
||||||
|
partial interface RTCPeerConnection {
|
||||||
|
// readonly attribute RTCSctpTransport? sctp;
|
||||||
|
RTCDataChannel createDataChannel(USVString label,
|
||||||
|
optional RTCDataChannelInit dataChannelDict = {});
|
||||||
|
attribute EventHandler ondatachannel;
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue