aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFernando Jiménez Moreno <ferjmoreno@gmail.com>2020-05-30 21:51:17 +0200
committerFernando Jiménez Moreno <ferjmoreno@gmail.com>2020-06-29 16:53:47 +0200
commit4e6d3e7cec0fa2467bdb7e6dd926facc4c37a28b (patch)
treec263ebdc9d97478c665443b8b438bf7026a8516b
parent5788882b16a30fee81c75ab26b7f6c8555b43693 (diff)
downloadservo-4e6d3e7cec0fa2467bdb7e6dd926facc4c37a28b.tar.gz
servo-4e6d3e7cec0fa2467bdb7e6dd926facc4c37a28b.zip
WebRTCDataChannel initial support
-rw-r--r--components/script/dom/bindings/trace.rs3
-rw-r--r--components/script/dom/mod.rs1
-rw-r--r--components/script/dom/rtcdatachannel.rs260
-rw-r--r--components/script/dom/rtcpeerconnection.rs15
-rw-r--r--components/script/dom/webidls/RTCDataChannel.webidl49
-rw-r--r--components/script/dom/webidls/RTCPeerConnection.webidl8
6 files changed, 335 insertions, 1 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 6208a7bc1ba..40ec44a62d5 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -128,7 +128,7 @@ use servo_media::player::video::VideoFrame;
use servo_media::player::Player;
use servo_media::streams::registry::MediaStreamId;
use servo_media::streams::MediaStreamType;
-use servo_media::webrtc::WebRtcController;
+use servo_media::webrtc::{WebRtcController, WebRtcDataChannelBackend};
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
use smallvec::SmallVec;
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!(Arc<Mutex<dyn Player>>);
unsafe_no_jsmanaged_fields!(WebRtcController);
+unsafe_no_jsmanaged_fields!(Box<dyn WebRtcDataChannelBackend>);
unsafe_no_jsmanaged_fields!(MediaStreamId, MediaStreamType);
unsafe_no_jsmanaged_fields!(Mutex<MediaFrameRenderer>);
unsafe_no_jsmanaged_fields!(ResourceFetchTiming);
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index 2ee17f3e74b..1024a37c3f4 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -486,6 +486,7 @@ pub mod raredata;
pub mod readablestream;
pub mod request;
pub mod response;
+pub mod rtcdatachannel;
pub mod rtcicecandidate;
pub mod rtcpeerconnection;
pub mod rtcpeerconnectioniceevent;
diff --git a/components/script/dom/rtcdatachannel.rs b/components/script/dom/rtcdatachannel.rs
new file mode 100644
index 00000000000..d7388729dbd
--- /dev/null
+++ b/components/script/dom/rtcdatachannel.rs
@@ -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(),
+ }
+ }
+}
diff --git a/components/script/dom/rtcpeerconnection.rs b/components/script/dom/rtcpeerconnection.rs
index fa8c5dda800..5ce0b109bbd 100644
--- a/components/script/dom/rtcpeerconnection.rs
+++ b/components/script/dom/rtcpeerconnection.rs
@@ -3,6 +3,7 @@
* 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::RTCIceCandidateBinding::RTCIceCandidateInit;
use crate::dom::bindings::codegen::Bindings::RTCPeerConnectionBinding::RTCPeerConnectionMethods;
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::DomObject;
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
+use crate::dom::bindings::str::USVString;
use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::dom::mediastream::MediaStream;
use crate::dom::mediastreamtrack::MediaStreamTrack;
use crate::dom::promise::Promise;
+use crate::dom::rtcdatachannel::RTCDataChannel;
use crate::dom::rtcicecandidate::RTCIceCandidate;
use crate::dom::rtcpeerconnectioniceevent::RTCPeerConnectionIceEvent;
use crate::dom::rtcsessiondescription::RTCSessionDescription;
@@ -448,6 +451,9 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
SetOnsignalingstatechange
);
+ // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-ondatachannel
+ event_handler!(datachannel, GetOndatachannel, SetOndatachannel);
+
/// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addicecandidate
fn AddIceCandidate(&self, candidate: &RTCIceCandidateInit, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp);
@@ -633,6 +639,15 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
// Step 11
// (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 {
diff --git a/components/script/dom/webidls/RTCDataChannel.webidl b/components/script/dom/webidls/RTCDataChannel.webidl
new file mode 100644
index 00000000000..e8a08969e55
--- /dev/null
+++ b/components/script/dom/webidls/RTCDataChannel.webidl
@@ -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"
+}; \ No newline at end of file
diff --git a/components/script/dom/webidls/RTCPeerConnection.webidl b/components/script/dom/webidls/RTCPeerConnection.webidl
index d2054343150..f53691a9a70 100644
--- a/components/script/dom/webidls/RTCPeerConnection.webidl
+++ b/components/script/dom/webidls/RTCPeerConnection.webidl
@@ -126,3 +126,11 @@ partial interface RTCPeerConnection {
// optional RTCRtpTransceiverInit init);
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;
+};