diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index db9d94e0c88..2f1d0a06ac7 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -112,6 +112,7 @@ use compositing::SendableFrameTree; use crossbeam_channel::{after, never, unbounded, Receiver, Sender}; use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg}; use embedder_traits::{Cursor, EmbedderMsg, EmbedderProxy, EventLoopWaker}; +use embedder_traits::{MediaSessionEvent, MediaSessionPlaybackState}; use euclid::{default::Size2D as UntypedSize2D, Size2D}; use gfx::font_cache_thread::FontCacheThread; use gfx_traits::Epoch; @@ -475,8 +476,8 @@ pub struct Constellation { /// Mechanism to force the compositor to process events. event_loop_waker: Option>, - /// Browser ID of the active media session, if any. - active_media_session: Option, + /// Browing context ID of the active media session. + active_media_session: Option, } /// State needed to construct a constellation. @@ -1778,6 +1779,30 @@ where new_value, ); }, + FromScriptMsg::MediaSessionEvent(browsing_context_id, event) => { + // Unlikely at this point, but we may receive events coming from + // different media sessions, so we set the active media session based + // on Playing events. + // The last media session claiming to be in playing state is set to + // the active media session. + // Events coming from inactive media sessions are discarded. + if self.active_media_session.is_some() { + match event { + MediaSessionEvent::PlaybackStateChange(ref state) => { + match state { + MediaSessionPlaybackState::Playing => (), + _ => return, + }; + }, + _ => (), + }; + } + self.active_media_session = Some(browsing_context_id); + self.embedder_proxy.send(( + Some(source_top_ctx_id), + EmbedderMsg::MediaSessionEvent(event), + )); + }, } } @@ -5042,8 +5067,7 @@ where ); }, }; - let msg = - ConstellationControlMsg::MediaSessionAction(top_level_browsing_context_id, action); + let msg = ConstellationControlMsg::MediaSessionAction(browsing_context_id, action); let result = match self.pipelines.get(&pipeline_id) { None => { return warn!( diff --git a/components/script/dom/mediasession.rs b/components/script/dom/mediasession.rs index 29d7108e3e3..2ad4586e6b2 100644 --- a/components/script/dom/mediasession.rs +++ b/components/script/dom/mediasession.rs @@ -16,9 +16,10 @@ use crate::dom::mediametadata::MediaMetadata; use crate::dom::window::Window; use crate::script_thread::ScriptThread; use dom_struct::dom_struct; -use embedder_traits::{EmbedderMsg, MediaSessionEvent}; -use msg::constellation_msg::TopLevelBrowsingContextId; +use embedder_traits::MediaSessionEvent; +use msg::constellation_msg::BrowsingContextId; use script_traits::MediaSessionActionType; +use script_traits::ScriptMsg; use std::collections::HashMap; use std::rc::Rc; @@ -39,7 +40,7 @@ pub struct MediaSession { impl MediaSession { #[allow(unrooted_must_root)] - fn new_inherited(browsing_context_id: TopLevelBrowsingContextId) -> MediaSession { + fn new_inherited(browsing_context_id: BrowsingContextId) -> MediaSession { let media_session = MediaSession { reflector_: Reflector::new(), metadata: Default::default(), @@ -52,7 +53,7 @@ impl MediaSession { } pub fn new(window: &Window) -> DomRoot { - let browsing_context_id = window.window_proxy().top_level_browsing_context_id(); + let browsing_context_id = window.window_proxy().browsing_context_id(); reflect_dom_object( Box::new(MediaSession::new_inherited(browsing_context_id)), window, @@ -74,7 +75,8 @@ impl MediaSession { pub fn send_event(&self, event: MediaSessionEvent) { let global = self.global(); let window = global.as_window(); - window.send_to_embedder(EmbedderMsg::MediaSessionEvent(event)); + let browsing_context_id = window.window_proxy().browsing_context_id(); + window.send_to_constellation(ScriptMsg::MediaSessionEvent(browsing_context_id, event)); } } @@ -121,10 +123,7 @@ impl MediaSessionMethods for MediaSession { impl Drop for MediaSession { fn drop(&mut self) { let global = self.global(); - let browsing_context_id = global - .as_window() - .window_proxy() - .top_level_browsing_context_id(); + let browsing_context_id = global.as_window().window_proxy().browsing_context_id(); ScriptThread::remove_media_session(browsing_context_id); } } diff --git a/components/script/dom/navigator.rs b/components/script/dom/navigator.rs index a759d3dbe54..d4cde572a47 100644 --- a/components/script/dom/navigator.rs +++ b/components/script/dom/navigator.rs @@ -194,7 +194,7 @@ impl NavigatorMethods for Navigator { /// https://w3c.github.io/mediasession/#dom-navigator-mediasession fn MediaSession(&self) -> DomRoot { self.mediasession.or_init(|| { - // There is a single MediaSession instance per top level browsing context + // There is a single MediaSession instance per browsing context // and only one active MediaSession globally. // // MediaSession creation can happen in two cases: @@ -206,7 +206,7 @@ impl NavigatorMethods for Navigator { // the script thread. let global = self.global(); let window = global.as_window(); - let browsing_context_id = window.window_proxy().top_level_browsing_context_id(); + let browsing_context_id = window.window_proxy().browsing_context_id(); match ScriptThread::get_media_session(browsing_context_id) { Some(session) => session, None => MediaSession::new(window), diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index e7b39d26420..886977e1945 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -701,7 +701,7 @@ pub struct ScriptThread { /// The MediaSessions known by this thread, if any. /// There can only be one active MediaSession. /// The constellation has the BrowsingContextId of the active MediaSession, if any. - media_sessions: DomRefCell>>, + media_sessions: DomRefCell>>, } /// In the event of thread panic, all data on the stack runs its destructor. However, there @@ -3938,7 +3938,7 @@ impl ScriptThread { fn handle_media_session_action( &self, - browsing_context_id: TopLevelBrowsingContextId, + browsing_context_id: BrowsingContextId, action: MediaSessionActionType, ) { match self.media_sessions.borrow().get(&browsing_context_id) { @@ -3973,7 +3973,7 @@ impl ScriptThread { pub fn register_media_session( media_session: &MediaSession, - browsing_context_id: TopLevelBrowsingContextId, + browsing_context_id: BrowsingContextId, ) { SCRIPT_THREAD_ROOT.with(|root| { let script_thread = unsafe { &*root.get().unwrap() }; @@ -3984,7 +3984,7 @@ impl ScriptThread { }) } - pub fn remove_media_session(browsing_context_id: TopLevelBrowsingContextId) { + pub fn remove_media_session(browsing_context_id: BrowsingContextId) { SCRIPT_THREAD_ROOT.with(|root| { let script_thread = unsafe { &*root.get().unwrap() }; script_thread @@ -3995,7 +3995,7 @@ impl ScriptThread { } pub fn get_media_session( - browsing_context_id: TopLevelBrowsingContextId, + browsing_context_id: BrowsingContextId, ) -> Option> { SCRIPT_THREAD_ROOT.with(|root| { let script_thread = unsafe { &*root.get().unwrap() }; diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 7b921db70e4..a732141a9ff 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -389,7 +389,7 @@ pub enum ConstellationControlMsg { /// Notifies the script thread about a new recorded paint metric. PaintMetric(PipelineId, ProgressiveWebMetricType, u64), /// Notifies the media session about a user requested media session action. - MediaSessionAction(TopLevelBrowsingContextId, MediaSessionActionType), + MediaSessionAction(BrowsingContextId, MediaSessionActionType), } impl fmt::Debug for ConstellationControlMsg { diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs index 64d6b1f5389..9db4e7ac7e2 100644 --- a/components/script_traits/script_msg.rs +++ b/components/script_traits/script_msg.rs @@ -17,7 +17,7 @@ use crate::WorkerGlobalScopeInit; use crate::WorkerScriptLoadOrigin; use canvas_traits::canvas::{CanvasId, CanvasMsg}; use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId}; -use embedder_traits::EmbedderMsg; +use embedder_traits::{EmbedderMsg, MediaSessionEvent}; use euclid::default::Size2D as UntypedSize2D; use euclid::Size2D; use gfx_traits::Epoch; @@ -306,6 +306,7 @@ impl fmt::Debug for ScriptMsg { GetClientWindow(..) => "GetClientWindow", GetScreenSize(..) => "GetScreenSize", GetScreenAvailSize(..) => "GetScreenAvailSize", + MediaSessionEvent(..) => "MediaSessionEvent", }; write!(formatter, "ScriptMsg::{}", variant) } diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 3da82d299fd..fa188bc5b3d 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -83,7 +83,6 @@ use constellation::{Constellation, InitialConstellationState, UnprivilegedPipeli use constellation::{FromCompositorLogger, FromScriptLogger}; use crossbeam_channel::{unbounded, Sender}; use embedder_traits::{EmbedderMsg, EmbedderProxy, EmbedderReceiver, EventLoopWaker}; -use embedder_traits::{MediaSessionEvent, MediaSessionPlaybackState}; use env_logger::Builder as EnvLoggerBuilder; use euclid::{Scale, Size2D}; #[cfg(all( @@ -272,8 +271,6 @@ pub struct Servo { embedder_events: Vec<(Option, EmbedderMsg)>, profiler_enabled: bool, webgl_thread_data: Option>, - /// Browser ID of the active media session, if any. - active_media_session: Option, } #[derive(Clone)] @@ -560,7 +557,6 @@ where embedder_events: Vec::new(), profiler_enabled: false, webgl_thread_data, - active_media_session: None, } } @@ -750,31 +746,6 @@ where self.embedder_events.push(event); }, - (EmbedderMsg::MediaSessionEvent(event), ShutdownState::NotShuttingDown) => { - // Unlikely at this point, but we may receive events coming from - // different media sessions, so we set the active media session based - // on Playing events. - // The last media session claiming to be in playing state is set to - // the active media session. - // Events coming from inactive media sessions are discarded. - if self.active_media_session.is_some() { - match event { - MediaSessionEvent::PlaybackStateChange(ref state) => { - match state { - MediaSessionPlaybackState::Playing => (), - _ => return, - }; - }, - _ => (), - }; - } - self.active_media_session = top_level_browsing_context; - self.embedder_events.push(( - top_level_browsing_context, - EmbedderMsg::MediaSessionEvent(event), - )); - }, - (msg, ShutdownState::NotShuttingDown) => { self.embedder_events.push((top_level_browsing_context, msg)); },