From 6233f78de48a92786b34426e96ffcfe05c6bc370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Fri, 4 Oct 2019 17:05:56 +0200 Subject: [PATCH] MediaSessionAction message from embedder to script thread --- components/compositing/windowing.rs | 6 +++- components/constellation/constellation.rs | 36 ++++++++++++++++++++++- components/script/script_thread.rs | 14 ++++++++- components/script_traits/lib.rs | 34 +++++++++++++++++++++ components/servo/lib.rs | 10 +++++++ 5 files changed, 97 insertions(+), 3 deletions(-) diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index decece701f4..d2fab70c234 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -10,7 +10,7 @@ use euclid::Scale; use gleam::gl; use keyboard_types::KeyboardEvent; use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId, TraversalDirection}; -use script_traits::{MouseButton, TouchEventType, TouchId, WheelDelta}; +use script_traits::{MediaSessionActionType, MouseButton, TouchEventType, TouchId, WheelDelta}; use servo_geometry::DeviceIndependentPixel; use servo_media::player::context::{GlApi, GlContext, NativeDisplay}; use servo_url::ServoUrl; @@ -102,6 +102,9 @@ pub enum WindowEvent { CaptureWebRender, /// Toggle sampling profiler with the given sampling rate and max duration. ToggleSamplingProfiler(Duration, Duration), + /// Sent when the user triggers a media action through the UA exposed media UI + /// (play, pause, seek, etc.). + MediaSessionAction(TopLevelBrowsingContextId, MediaSessionActionType), } impl Debug for WindowEvent { @@ -132,6 +135,7 @@ impl Debug for WindowEvent { WindowEvent::CaptureWebRender => write!(f, "CaptureWebRender"), WindowEvent::ToggleSamplingProfiler(..) => write!(f, "ToggleSamplingProfiler"), WindowEvent::ExitFullScreen(..) => write!(f, "ExitFullScreen"), + WindowEvent::MediaSessionAction(..) => write!(f, "MediaSessionAction"), } } } diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index c24883f99e5..8f549ea685e 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -139,7 +139,6 @@ use net_traits::{self, FetchResponseMsg, IpcSend, ResourceThreads}; use profile_traits::mem; use profile_traits::time; use script_traits::CompositorEvent::{MouseButtonEvent, MouseMoveEvent}; -use script_traits::MouseEventType; use script_traits::{webdriver_msg, LogEntry, ScriptToConstellationChan, ServiceWorkerMsg}; use script_traits::{ AnimationState, AnimationTickType, AuxiliaryBrowsingContextLoadInfo, CompositorEvent, @@ -154,6 +153,7 @@ use script_traits::{ }; use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory}; use script_traits::{MessagePortMsg, PortMessageTask, StructuredSerializedData}; +use script_traits::{MediaSessionActionType, MouseEventType}; use script_traits::{SWManagerMsg, ScopeThings, UpdatePipelineIdReason, WebDriverCommandMsg}; use serde::{Deserialize, Serialize}; use servo_config::{opts, pref}; @@ -1541,6 +1541,9 @@ where FromCompositorMsg::ExitFullScreen(top_level_browsing_context_id) => { self.handle_exit_fullscreen_msg(top_level_browsing_context_id); }, + FromCompositorMsg::MediaSessionAction(top_level_browsing_context_id, action) => { + self.handle_media_session_action_msg(top_level_browsing_context_id, action); + }, } } @@ -5019,4 +5022,35 @@ where .send(ToCompositorMsg::SetFrameTree(frame_tree)); } } + + fn handle_media_session_action_msg( + &mut self, + top_level_browsing_context_id: TopLevelBrowsingContextId, + action: MediaSessionActionType, + ) { + let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); + let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { + Some(browsing_context) => browsing_context.pipeline_id, + None => { + return warn!( + "Browsing context {} got media session action request after closure.", + browsing_context_id + ); + }, + }; + let msg = + ConstellationControlMsg::MediaSessionAction(top_level_browsing_context_id, action); + let result = match self.pipelines.get(&pipeline_id) { + None => { + return warn!( + "Pipeline {} got media session action request after closure.", + pipeline_id + ) + }, + Some(pipeline) => pipeline.event_loop.send(msg), + }; + if let Err(e) = result { + self.handle_send_error(pipeline_id, e); + } + } } diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 2bd7cc4907b..1c1a7bd9538 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -139,7 +139,7 @@ use script_traits::{ DiscardBrowsingContext, DocumentActivity, EventResult, HistoryEntryReplacement, }; use script_traits::{InitialScriptState, JsEvalResult, LayoutMsg, LoadData, LoadOrigin}; -use script_traits::{MouseButton, MouseEventType, NewLayoutInfo}; +use script_traits::{MediaSessionActionType, MouseButton, MouseEventType, NewLayoutInfo}; use script_traits::{Painter, ProgressiveWebMetricType, ScriptMsg, ScriptThreadFactory}; use script_traits::{ScriptToConstellationChan, TimerEvent, TimerSchedulerMsg}; use script_traits::{TimerSource, TouchEventType, TouchId, UntrustedNodeAddress, WheelDelta}; @@ -1720,6 +1720,7 @@ impl ScriptThread { WebVREvents(id, ..) => Some(id), PaintMetric(..) => None, ExitFullScreen(id, ..) => Some(id), + MediaSessionAction(..) => None, } }, MixedMessage::FromDevtools(_) => None, @@ -1949,6 +1950,9 @@ impl ScriptThread { ConstellationControlMsg::PaintMetric(pipeline_id, metric_type, metric_value) => { self.handle_paint_metric(pipeline_id, metric_type, metric_value) }, + ConstellationControlMsg::MediaSessionAction(browsing_context_id, action) => { + self.handle_media_session_action(browsing_context_id, action) + }, msg @ ConstellationControlMsg::AttachLayout(..) | msg @ ConstellationControlMsg::Viewport(..) | msg @ ConstellationControlMsg::SetScrollState(..) | @@ -3932,6 +3936,14 @@ impl ScriptThread { } } + fn handle_media_session_action( + &self, + browsing_context_id: TopLevelBrowsingContextId, + action: MediaSessionActionType, + ) { + // TODO + } + pub fn enqueue_microtask(job: Microtask) { 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 0212ae021b6..4bfa594688a 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -388,6 +388,8 @@ pub enum ConstellationControlMsg { WebVREvents(PipelineId, Vec), /// 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), } impl fmt::Debug for ConstellationControlMsg { @@ -426,6 +428,7 @@ impl fmt::Debug for ConstellationControlMsg { WebVREvents(..) => "WebVREvents", PaintMetric(..) => "PaintMetric", ExitFullScreen(..) => "ExitFullScreen", + MediaSessionAction(..) => "MediaSessionAction", }; write!(formatter, "ConstellationControlMsg::{}", variant) } @@ -877,6 +880,8 @@ pub enum ConstellationMsg { DisableProfiler, /// Request to exit from fullscreen mode ExitFullScreen(TopLevelBrowsingContextId), + /// Media session action. + MediaSessionAction(TopLevelBrowsingContextId, MediaSessionActionType), } impl fmt::Debug for ConstellationMsg { @@ -907,6 +912,7 @@ impl fmt::Debug for ConstellationMsg { EnableProfiler(..) => "EnableProfiler", DisableProfiler => "DisableProfiler", ExitFullScreen(..) => "ExitFullScreen", + MediaSessionAction(..) => "MediaSessionAction", }; write!(formatter, "ConstellationMsg::{}", variant) } @@ -1052,4 +1058,32 @@ pub enum MessagePortMsg { RemoveMessagePort(MessagePortId), /// Handle a new port-message-task. NewTask(MessagePortId, PortMessageTask), + +/// The type of MediaSession action. +/// https://w3c.github.io/mediasession/#enumdef-mediasessionaction +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum MediaSessionActionType { + /// The action intent is to resume playback. + Play, + /// The action intent is to pause the currently active playback. + Pause, + /// The action intent is to move the playback time backward by a short period (i.e. a few + /// seconds). + SeekBackward, + /// The action intent is to move the playback time forward by a short period (i.e. a few + /// seconds). + SeekForward, + /// The action intent is to either start the current playback from the beginning if the + /// playback has a notion, of beginning, or move to the previous item in the playlist if the + /// playback has a notion of playlist. + PreviousTrack, + /// The action is to move to the playback to the next item in the playlist if the playback has + /// a notion of playlist. + NextTrack, + /// The action intent is to skip the advertisement that is currently playing. + SkipAd, + /// The action intent is to stop the playback and clear the state if appropriate. + Stop, + /// The action intent is to move the playback time to a specific time. + SeekTo, } diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 3d4b7bf14d3..67751234111 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -713,6 +713,16 @@ where ); } }, + + WindowEvent::MediaSessionAction(ctx, a) => { + let msg = ConstellationMsg::MediaSessionAction(ctx, a); + if let Err(e) = self.constellation_chan.send(msg) { + warn!( + "Sending MediaSessionAction message to constellation failed ({:?}).", + e + ); + } + }, } }