diff --git a/components/atoms/static_atoms.txt b/components/atoms/static_atoms.txt index 74f24a23e30..e720f8435b3 100644 --- a/components/atoms/static_atoms.txt +++ b/components/atoms/static_atoms.txt @@ -37,6 +37,7 @@ gattserverdisconnected hashchange hidden icecandidate +icegatheringstatechange image input invalid diff --git a/components/script/dom/rtcpeerconnection.rs b/components/script/dom/rtcpeerconnection.rs index 0a1c41cf3f9..13e58b14038 100644 --- a/components/script/dom/rtcpeerconnection.rs +++ b/components/script/dom/rtcpeerconnection.rs @@ -7,7 +7,7 @@ use crate::dom::bindings::codegen::Bindings::RTCIceCandidateBinding::RTCIceCandi use crate::dom::bindings::codegen::Bindings::RTCPeerConnectionBinding; use crate::dom::bindings::codegen::Bindings::RTCPeerConnectionBinding::RTCPeerConnectionMethods; use crate::dom::bindings::codegen::Bindings::RTCPeerConnectionBinding::{ - RTCAnswerOptions, RTCBundlePolicy, RTCConfiguration, RTCOfferOptions, + RTCAnswerOptions, RTCBundlePolicy, RTCConfiguration, RTCIceGatheringState, RTCOfferOptions, }; use crate::dom::bindings::codegen::Bindings::RTCSessionDescriptionBinding::{ RTCSdpType, RTCSessionDescriptionInit, @@ -36,7 +36,8 @@ use dom_struct::dom_struct; use servo_media::streams::MediaStream as BackendMediaStream; use servo_media::webrtc::{ - BundlePolicy, IceCandidate, SdpType, SessionDescription, WebRtcController, WebRtcSignaller, + BundlePolicy, GatheringState, IceCandidate, SdpType, SessionDescription, WebRtcController, + WebRtcSignaller, }; use servo_media::ServoMedia; use servo_media_auto::Backend; @@ -59,6 +60,7 @@ pub struct RTCPeerConnection { answer_promises: DomRefCell>>, local_description: MutNullableDom, remote_description: MutNullableDom, + gathering_state: Cell, } struct RTCSignaller { @@ -90,6 +92,17 @@ impl WebRtcSignaller for RTCSignaller { ); } + fn update_gathering_state(&self, state: GatheringState) { + let this = self.trusted.clone(); + let _ = self.task_source.queue_with_canceller( + task!(update_gathering_state: move || { + let this = this.root(); + this.update_gathering_state(state); + }), + &self.canceller, + ); + } + fn on_add_stream(&self, _: Box) {} fn close(&self) { @@ -108,6 +121,7 @@ impl RTCPeerConnection { answer_promises: DomRefCell::new(vec![]), local_description: Default::default(), remote_description: Default::default(), + gathering_state: Cell::new(RTCIceGatheringState::New), } } @@ -198,6 +212,55 @@ impl RTCPeerConnection { event.upcast::().fire(self.upcast()); } + /// https://www.w3.org/TR/webrtc/#update-ice-gathering-state + fn update_gathering_state(&self, state: GatheringState) { + // step 1 + if self.closed.get() { + return; + } + + // step 2 (state derivation already done by gstreamer) + let state: RTCIceGatheringState = state.into(); + + // step 3 + if state == self.gathering_state.get() { + return; + } + + // step 4 + self.gathering_state.set(state); + + // step 5 + let event = Event::new( + &self.global(), + atom!("icegatheringstatechange"), + EventBubbles::DoesNotBubble, + EventCancelable::NotCancelable, + ); + event.upcast::().fire(self.upcast()); + + // step 6 + if state == RTCIceGatheringState::Complete { + let event = RTCPeerConnectionIceEvent::new( + &self.global(), + atom!("icecandidate"), + None, + None, + true, + ); + event.upcast::().fire(self.upcast()); + } + + // step 5 + let event = Event::new( + &self.global(), + atom!("icegatheringstatechange"), + EventBubbles::DoesNotBubble, + EventCancelable::NotCancelable, + ); + event.upcast::().fire(self.upcast()); + } + fn create_offer(&self) { let generation = self.offer_answer_generation.get(); let (task_source, canceller) = self @@ -269,6 +332,13 @@ impl RTCPeerConnectionMethods for RTCPeerConnection { /// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-icecandidate event_handler!(icecandidate, GetOnicecandidate, SetOnicecandidate); + /// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-icegatheringstatechange + event_handler!( + icegatheringstatechange, + GetOnicegatheringstatechange, + SetOnicegatheringstatechange + ); + /// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-onnegotiationneeded event_handler!( negotiationneeded, @@ -419,6 +489,11 @@ impl RTCPeerConnectionMethods for RTCPeerConnection { self.controller.borrow().as_ref().unwrap().add_stream(track); } } + + /// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-icegatheringstate + fn IceGatheringState(&self) -> RTCIceGatheringState { + self.gathering_state.get() + } } impl From for RTCSessionDescriptionInit { @@ -450,3 +525,14 @@ impl<'a> From<&'a RTCSessionDescriptionInit> for SessionDescription { } } } + + +impl From for RTCIceGatheringState { + fn from(state: GatheringState) -> Self { + match state { + GatheringState::New => RTCIceGatheringState::New, + GatheringState::Gathering => RTCIceGatheringState::Gathering, + GatheringState::Complete => RTCIceGatheringState::Complete, + } + } +} diff --git a/components/script/dom/webidls/RTCPeerConnection.webidl b/components/script/dom/webidls/RTCPeerConnection.webidl index c79dba097bf..ea1930a0561 100644 --- a/components/script/dom/webidls/RTCPeerConnection.webidl +++ b/components/script/dom/webidls/RTCPeerConnection.webidl @@ -19,7 +19,7 @@ interface RTCPeerConnection : EventTarget { // readonly attribute RTCSessionDescription? pendingRemoteDescription; Promise addIceCandidate(optional RTCIceCandidateInit candidate); // readonly attribute RTCSignalingState signalingState; - // readonly attribute RTCIceGatheringState iceGatheringState; + readonly attribute RTCIceGatheringState iceGatheringState; // readonly attribute RTCIceConnectionState iceConnectionState; // readonly attribute RTCPeerConnectionState connectionState; // readonly attribute boolean? canTrickleIceCandidates; @@ -32,7 +32,7 @@ interface RTCPeerConnection : EventTarget { // attribute EventHandler onicecandidateerror; // attribute EventHandler onsignalingstatechange; // attribute EventHandler oniceconnectionstatechange; - // attribute EventHandler onicegatheringstatechange; + attribute EventHandler onicegatheringstatechange; // attribute EventHandler onconnectionstatechange; // removed from spec, but still shipped by browsers @@ -89,3 +89,9 @@ dictionary RTCOfferOptions : RTCOfferAnswerOptions { dictionary RTCAnswerOptions : RTCOfferAnswerOptions { }; + +enum RTCIceGatheringState { + "new", + "gathering", + "complete" +};