Register media instance with session and prepare communication with embedder

This commit is contained in:
Fernando Jiménez Moreno 2019-10-08 10:18:13 +02:00
parent 9c329a7935
commit 4d147d2c56
8 changed files with 107 additions and 4 deletions

View file

@ -15,8 +15,10 @@ use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::HTMLMediaE
use crate::dom::bindings::codegen::Bindings::HTMLSourceElementBinding::HTMLSourceElementMethods;
use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorConstants::*;
use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethods;
use crate::dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorBinding::NavigatorMethods;
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeBinding::NodeMethods;
use crate::dom::bindings::codegen::Bindings::TextTrackBinding::{TextTrackKind, TextTrackMode};
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
use crate::dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId};
use crate::dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId};
use crate::dom::bindings::codegen::UnionTypes::{
@ -78,6 +80,7 @@ use net_traits::request::{Destination, Referrer};
use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseListener, Metadata};
use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType};
use script_layout_interface::HTMLMediaData;
use script_traits::MediaSessionEvent;
use servo_config::pref;
use servo_media::player::audio::AudioRenderer;
use servo_media::player::video::{VideoFrame, VideoFrameRenderer};
@ -592,7 +595,6 @@ impl HTMLMediaElement {
match (old_ready_state, ready_state) {
(ReadyState::HaveNothing, ReadyState::HaveMetadata) => {
task_source.queue_simple_event(self.upcast(), atom!("loadedmetadata"), &window);
// No other steps are applicable in this case.
return;
},
@ -1883,6 +1885,12 @@ impl HTMLMediaElement {
self.media_element_load_algorithm();
}
}
fn send_media_session_event(&self, event: MediaSessionEvent) {
let global = self.global();
let media_session = global.as_window().Navigator().MediaSession();
media_session.send_event(event);
}
}
// XXX Placeholder for [https://github.com/servo/servo/issues/22293]

View file

@ -11,12 +11,13 @@ use crate::dom::bindings::codegen::Bindings::MediaSessionBinding::MediaSessionMe
use crate::dom::bindings::codegen::Bindings::MediaSessionBinding::MediaSessionPlaybackState;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::htmlmediaelement::HTMLMediaElement;
use crate::dom::mediametadata::MediaMetadata;
use crate::dom::window::Window;
use crate::script_thread::ScriptThread;
use dom_struct::dom_struct;
use msg::constellation_msg::TopLevelBrowsingContextId;
use script_traits::MediaSessionActionType;
use script_traits::{MediaSessionActionType, MediaSessionEvent, ScriptMsg};
use std::collections::HashMap;
use std::rc::Rc;
@ -30,6 +31,9 @@ pub struct MediaSession {
/// https://w3c.github.io/mediasession/#supported-media-session-actions
#[ignore_malloc_size_of = "Rc"]
action_handlers: DomRefCell<HashMap<MediaSessionActionType, Rc<MediaSessionActionHandler>>>,
/// The media instance controlled by this media session.
/// For now only HTMLMediaElements are controlled by media sessions.
media_instance: MutNullableDom<HTMLMediaElement>,
}
impl MediaSession {
@ -40,6 +44,7 @@ impl MediaSession {
metadata: Default::default(),
playback_state: DomRefCell::new(MediaSessionPlaybackState::None),
action_handlers: DomRefCell::new(HashMap::new()),
media_instance: Default::default(),
};
ScriptThread::register_media_session(&media_session, browsing_context_id);
media_session
@ -63,6 +68,18 @@ impl MediaSession {
}
// TODO default action.
}
pub fn send_event(&self, event: MediaSessionEvent) {
let global = self.global();
let browser_id = global
.as_window()
.window_proxy()
.top_level_browsing_context_id();
let _ = global
.script_to_constellation_chan()
.send(ScriptMsg::MediaSessionEventMsg(browser_id, event))
.unwrap();
}
}
impl MediaSessionMethods for MediaSession {

View file

@ -21,6 +21,7 @@ use crate::dom::promise::Promise;
use crate::dom::serviceworkercontainer::ServiceWorkerContainer;
use crate::dom::window::Window;
use crate::dom::xr::XR;
use crate::script_thread::ScriptThread;
use dom_struct::dom_struct;
use std::rc::Rc;
@ -192,7 +193,24 @@ impl NavigatorMethods for Navigator {
/// https://w3c.github.io/mediasession/#dom-navigator-mediasession
fn MediaSession(&self) -> DomRoot<MediaSession> {
self.mediasession
.or_init(|| MediaSession::new(self.global().as_window()))
self.mediasession.or_init(|| {
// There is a single MediaSession instance per top level browsing context
// and only one active MediaSession globally.
//
// MediaSession creation can happen in two cases:
//
// - If content gets `navigator.mediaSession`
// - If a media instance (HTMLMediaElement so far) starts playing media.
//
// The MediaSession constructor is in charge of registering itself with
// the script thread.
let global = self.global();
let window = global.as_window();
let browsing_context_id = window.window_proxy().top_level_browsing_context_id();
match ScriptThread::get_media_session(browsing_context_id) {
Some(session) => session,
None => MediaSession::new(window),
}
})
}
}