Media UI basic functionality

This commit is contained in:
Fernando Jiménez Moreno 2019-04-16 11:46:55 +02:00
parent 1c02fc94a8
commit a664449681
10 changed files with 420 additions and 35 deletions

View file

@ -60,7 +60,8 @@ pub enum Resource {
PresentationalHintsCSS,
QuirksModeCSS,
RippyPNG,
MediaControls,
MediaControlsCSS,
MediaControlsJS,
}
pub trait ResourceReaderMethods {
@ -95,7 +96,8 @@ fn resources_for_tests() -> Box<dyn ResourceReaderMethods + Sync + Send> {
Resource::PresentationalHintsCSS => "presentational-hints.css",
Resource::QuirksModeCSS => "quirks-mode.css",
Resource::RippyPNG => "rippy.png",
Resource::MediaControls => "media_controls.js",
Resource::MediaControlsCSS => "media_controls.css",
Resource::MediaControlsJS => "media_controls.js",
};
let mut path = env::current_exe().unwrap();
path = path.canonicalize().unwrap();

View file

@ -706,7 +706,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let mut abs_descendants = AbsoluteDescendants::new();
let mut legalizer = Legalizer::new();
if !node.is_replaced_content() ||
node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLMediaElement)) {
node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLMediaElement))
{
for kid in node.children() {
if kid.get_pseudo_element_type() != PseudoElementType::Normal {
self.process(&kid);
@ -1249,7 +1250,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
// Go to a path that concatenates our kids' fragments.
self.build_fragments_for_nonreplaced_inline_content(node)
} else {
if node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLMediaElement)) {
if node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLMediaElement))
{
// Do not treat media elements as leafs.
self.build_flow_for_block(node, None)
} else {

View file

@ -41,6 +41,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::htmlscriptelement::HTMLScriptElement;
use crate::dom::htmlsourceelement::HTMLSourceElement;
use crate::dom::htmlstyleelement::HTMLStyleElement;
use crate::dom::htmlvideoelement::HTMLVideoElement;
use crate::dom::mediaerror::MediaError;
use crate::dom::mediastream::MediaStream;
@ -1737,21 +1738,41 @@ impl HTMLMediaElement {
&document,
ElementCreator::ScriptCreated,
);
let mut media_controls = resources::read_string(EmbedderResource::MediaControls);
let mut media_controls_script =
resources::read_string(EmbedderResource::MediaControlsJS);
// This is our hacky way to temporarily workaround the lack of a privileged
// JS context.
// The media controls UI accesses the document.servoGetMediaControls(id) API
// to get an instance to the media controls ShadowRoot.
// `id` needs to match the internally generated UUID assigned to a media element.
let id = document.register_media_controls(&shadow_root);
let media_controls = media_controls.as_mut_str().replace("@@@id@@@", &id);
let media_controls_script = media_controls_script.as_mut_str().replace("@@@id@@@", &id);
*self.media_controls_id.borrow_mut() = Some(id);
script
.upcast::<Node>()
.SetTextContent(Some(DOMString::from(media_controls)));
.SetTextContent(Some(DOMString::from(media_controls_script)));
if let Err(e) = shadow_root
.upcast::<Node>()
.AppendChild(&*script.upcast::<Node>())
{
warn!("Could not render media controls {:?}", e);
return;
}
let media_controls_style = resources::read_string(EmbedderResource::MediaControlsCSS);
let style = HTMLStyleElement::new(
local_name!("script"),
None,
&document,
ElementCreator::ScriptCreated,
);
style
.upcast::<Node>()
.SetTextContent(Some(DOMString::from(media_controls_style)));
if let Err(e) = shadow_root
.upcast::<Node>()
.AppendChild(&*style.upcast::<Node>())
{
warn!("Could not render media controls {:?}", e);
}

View file

@ -116,7 +116,11 @@ impl HTMLStyleElement {
.upcast::<Node>()
.containing_shadow_root() {
if shadow_root.is_user_agent_widget() {
(ServoUrl::parse(&format!("chrome://{:?}", window.get_url().to_string())).unwrap(), Origin::UserAgent)
(
ServoUrl::parse(&format!("chrome://{:?}", window.get_url().to_string()))
.unwrap(),
Origin::UserAgent,
)
} else {
(window.get_url(), Origin::Author)
}

View file

@ -52,7 +52,11 @@ pub struct ShadowRoot {
impl ShadowRoot {
#[allow(unrooted_must_root)]
fn new_inherited(host: &Element, document: &Document, is_widget: IsUserAgentWidget) -> ShadowRoot {
fn new_inherited(
host: &Element,
document: &Document,
is_widget: IsUserAgentWidget,
) -> ShadowRoot {
let document_fragment = DocumentFragment::new_inherited(document);
let node = document_fragment.upcast::<Node>();
node.set_flag(NodeFlags::IS_IN_SHADOW_TREE, true);
@ -72,7 +76,11 @@ impl ShadowRoot {
}
}
pub fn new(host: &Element, document: &Document, is_widget: IsUserAgentWidget) -> DomRoot<ShadowRoot> {
pub fn new(
host: &Element,
document: &Document,
is_widget: IsUserAgentWidget,
) -> DomRoot<ShadowRoot> {
reflect_dom_object(
Box::new(ShadowRoot::new_inherited(host, document, is_widget)),
document.window(),

View file

@ -143,7 +143,8 @@ impl FetchResponseListener for StylesheetContext {
let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s);
let final_url = if let Some(ref shadow_root) = self.shadow_root {
if shadow_root.root().is_user_agent_widget() {
ServoUrl::parse(&format!("chrome://{:?}", metadata.final_url.to_string())).unwrap()
ServoUrl::parse(&format!("chrome://{:?}", metadata.final_url.to_string()))
.unwrap()
} else {
metadata.final_url
}