diff options
author | Fernando Jiménez Moreno <ferjmoreno@gmail.com> | 2020-05-30 21:51:17 +0200 |
---|---|---|
committer | Fernando Jiménez Moreno <ferjmoreno@gmail.com> | 2020-06-29 16:53:47 +0200 |
commit | 4e6d3e7cec0fa2467bdb7e6dd926facc4c37a28b (patch) | |
tree | c263ebdc9d97478c665443b8b438bf7026a8516b | |
parent | 5788882b16a30fee81c75ab26b7f6c8555b43693 (diff) | |
download | servo-4e6d3e7cec0fa2467bdb7e6dd926facc4c37a28b.tar.gz servo-4e6d3e7cec0fa2467bdb7e6dd926facc4c37a28b.zip |
WebRTCDataChannel initial support
-rw-r--r-- | components/script/dom/bindings/trace.rs | 3 | ||||
-rw-r--r-- | components/script/dom/mod.rs | 1 | ||||
-rw-r--r-- | components/script/dom/rtcdatachannel.rs | 260 | ||||
-rw-r--r-- | components/script/dom/rtcpeerconnection.rs | 15 | ||||
-rw-r--r-- | components/script/dom/webidls/RTCDataChannel.webidl | 49 | ||||
-rw-r--r-- | components/script/dom/webidls/RTCPeerConnection.webidl | 8 |
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; +}; |