diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index e92d1d5c452..c128b6d9154 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -101,6 +101,7 @@ use servo_media::audio::graph::NodeId; use servo_media::audio::panner_node::{DistanceModel, PanningModel}; use servo_media::audio::param::ParamType; use servo_media::player::Player; +use servo_media::webrtc::WebRtcController; use servo_media::Backend; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; use smallvec::SmallVec; @@ -483,6 +484,7 @@ unsafe_no_jsmanaged_fields!(AudioContext); unsafe_no_jsmanaged_fields!(NodeId); unsafe_no_jsmanaged_fields!(AnalysisEngine, DistanceModel, PanningModel, ParamType); unsafe_no_jsmanaged_fields!(dyn Player); +unsafe_no_jsmanaged_fields!(WebRtcController); unsafe_no_jsmanaged_fields!(Mutex); unsafe_no_jsmanaged_fields!(RenderApiSender); unsafe_no_jsmanaged_fields!(ResourceFetchTiming); diff --git a/components/script/dom/rtcicecandidate.rs b/components/script/dom/rtcicecandidate.rs index 6c157844dbd..7ced25fc29c 100644 --- a/components/script/dom/rtcicecandidate.rs +++ b/components/script/dom/rtcicecandidate.rs @@ -2,8 +2,10 @@ * 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::codegen::Bindings::RTCIceCandidateBinding::{self, RTCIceCandidateMethods}; use crate::dom::bindings::codegen::Bindings::RTCIceCandidateBinding::RTCIceCandidateInit; +use crate::dom::bindings::codegen::Bindings::RTCIceCandidateBinding::{ + self, RTCIceCandidateMethods, +}; use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::reflector::reflect_dom_object; use crate::dom::bindings::reflector::{DomObject, Reflector}; @@ -23,18 +25,35 @@ pub struct RTCIceCandidate { } impl RTCIceCandidate { - pub fn new_inherited(candidate: DOMString, sdp_m_id: Option, - sdp_m_line_index: Option, username_fragment: Option) -> RTCIceCandidate { + pub fn new_inherited( + candidate: DOMString, + sdp_m_id: Option, + sdp_m_line_index: Option, + username_fragment: Option, + ) -> RTCIceCandidate { RTCIceCandidate { reflector: Reflector::new(), - candidate, sdp_m_id, sdp_m_line_index, username_fragment + candidate, + sdp_m_id, + sdp_m_line_index, + username_fragment, } } - pub fn new(global: &GlobalScope, candidate: DOMString, sdp_m_id: Option, - sdp_m_line_index: Option, username_fragment: Option) -> DomRoot { + pub fn new( + global: &GlobalScope, + candidate: DOMString, + sdp_m_id: Option, + sdp_m_line_index: Option, + username_fragment: Option, + ) -> DomRoot { reflect_dom_object( - Box::new(RTCIceCandidate::new_inherited(candidate, sdp_m_id, sdp_m_line_index, username_fragment)), + Box::new(RTCIceCandidate::new_inherited( + candidate, + sdp_m_id, + sdp_m_line_index, + username_fragment, + )), global, RTCIceCandidateBinding::Wrap, ) @@ -45,15 +64,20 @@ impl RTCIceCandidate { config: &RTCIceCandidateInit, ) -> Fallible> { if config.sdpMid.is_none() && config.sdpMLineIndex.is_none() { - return Err(Error::Type(format!("one of sdpMid and sdpMLineIndex must be set"))); + return Err(Error::Type(format!( + "one of sdpMid and sdpMLineIndex must be set" + ))); } - Ok(RTCIceCandidate::new(&window.global(), config.candidate.clone(), - config.sdpMid.clone(), config.sdpMLineIndex, - config.usernameFragment.clone())) + Ok(RTCIceCandidate::new( + &window.global(), + config.candidate.clone(), + config.sdpMid.clone(), + config.sdpMLineIndex, + config.usernameFragment.clone(), + )) } } - impl RTCIceCandidateMethods for RTCIceCandidate { /// https://www.w3.org/TR/webrtc/#dom-rtcicecandidate-candidate fn Candidate(&self) -> DOMString { diff --git a/components/script/dom/rtcpeerconnection.rs b/components/script/dom/rtcpeerconnection.rs index 6af09b5c387..41381ba43eb 100644 --- a/components/script/dom/rtcpeerconnection.rs +++ b/components/script/dom/rtcpeerconnection.rs @@ -2,35 +2,86 @@ * 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::RTCPeerConnectionBinding; use crate::dom::bindings::codegen::Bindings::RTCPeerConnectionBinding::RTCConfiguration; use crate::dom::bindings::error::Fallible; +use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::reflect_dom_object; use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::root::DomRoot; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::window::Window; +use crate::task::TaskCanceller; +use crate::task_source::networking::NetworkingTaskSource; +use crate::task_source::TaskSource; use dom_struct::dom_struct; +use servo_media::webrtc::MediaStream as BackendMediaStream; +use servo_media::webrtc::{IceCandidate, WebRtcController, WebRtcSignaller}; +use servo_media::ServoMedia; + #[dom_struct] pub struct RTCPeerConnection { eventtarget: EventTarget, + #[ignore_malloc_size_of = "defined in servo-media"] + controller: DomRefCell>, +} + +struct RTCSignaller { + trusted: Trusted, + task_source: NetworkingTaskSource, + canceller: TaskCanceller, +} + +impl WebRtcSignaller for RTCSignaller { + fn on_ice_candidate(&self, _: &WebRtcController, candidate: IceCandidate) { + let this = self.trusted.clone(); + let _ = self.task_source.queue_with_canceller( + task!(on_ice_candidate: move || { + let this = this.root(); + this.on_ice_candidate(candidate); + }), + &self.canceller, + ); + } + + fn on_negotiation_needed(&self, _: &WebRtcController) { + let this = self.trusted.clone(); + let _ = self.task_source.queue_with_canceller( + task!(on_negotiation_needed: move || { + let this = this.root(); + this.on_negotiation_needed(); + }), + &self.canceller, + ); + } + + fn on_add_stream(&self, _: Box) {} + + fn close(&self) { + // do nothing + } } impl RTCPeerConnection { pub fn new_inherited() -> RTCPeerConnection { RTCPeerConnection { eventtarget: EventTarget::new_inherited(), + controller: DomRefCell::new(None), } } pub fn new(global: &GlobalScope) -> DomRoot { - reflect_dom_object( + let this = reflect_dom_object( Box::new(RTCPeerConnection::new_inherited()), global, RTCPeerConnectionBinding::Wrap, - ) + ); + let signaller = this.make_signaller(); + *this.controller.borrow_mut() = Some(ServoMedia::get().unwrap().create_webrtc(signaller)); + this } pub fn Constructor( @@ -39,4 +90,26 @@ impl RTCPeerConnection { ) -> Fallible> { Ok(RTCPeerConnection::new(&window.global())) } + + fn make_signaller(&self) -> Box { + let trusted = Trusted::new(self); + let (task_source, canceller) = self + .global() + .as_window() + .task_manager() + .networking_task_source_with_canceller(); + Box::new(RTCSignaller { + trusted, + task_source, + canceller, + }) + } + + fn on_ice_candidate(&self, _candidate: IceCandidate) { + // todo + } + + fn on_negotiation_needed(&self) { + // todo + } }