mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Added AudioTrack, AudioTrackList, VideoTrack, VideoTrackList, and TrackEvent interfaces
This commit is contained in:
parent
4d8d54fc00
commit
cac4aa56f7
19 changed files with 974 additions and 138 deletions
97
components/script/dom/audiotrack.rs
Normal file
97
components/script/dom/audiotrack.rs
Normal file
|
@ -0,0 +1,97 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::dom::bindings::codegen::Bindings::AudioTrackBinding::{self, AudioTrackMethods};
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||
use crate::dom::bindings::root::DomRoot;
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use std::cell::Cell;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct AudioTrack {
|
||||
reflector_: Reflector,
|
||||
id: DOMString,
|
||||
kind: DOMString,
|
||||
label: DOMString,
|
||||
language: DOMString,
|
||||
enabled: Cell<bool>,
|
||||
}
|
||||
|
||||
impl AudioTrack {
|
||||
pub fn new_inherited(
|
||||
id: DOMString,
|
||||
kind: DOMString,
|
||||
label: DOMString,
|
||||
language: DOMString,
|
||||
) -> AudioTrack {
|
||||
AudioTrack {
|
||||
reflector_: Reflector::new(),
|
||||
id: id.into(),
|
||||
kind: kind.into(),
|
||||
label: label.into(),
|
||||
language: language.into(),
|
||||
enabled: Cell::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
window: &Window,
|
||||
id: DOMString,
|
||||
kind: DOMString,
|
||||
label: DOMString,
|
||||
language: DOMString,
|
||||
) -> DomRoot<AudioTrack> {
|
||||
reflect_dom_object(
|
||||
Box::new(AudioTrack::new_inherited(id, kind, label, language)),
|
||||
window,
|
||||
AudioTrackBinding::Wrap,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn id(&self) -> DOMString {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
pub fn enabled(&self) -> bool {
|
||||
self.enabled.get()
|
||||
}
|
||||
|
||||
pub fn set_enabled(&self, value: bool) {
|
||||
self.enabled.set(value);
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioTrackMethods for AudioTrack {
|
||||
// https://html.spec.whatwg.org/multipage/#dom-audiotrack-id
|
||||
fn Id(&self) -> DOMString {
|
||||
self.id()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-audiotrack-kind
|
||||
fn Kind(&self) -> DOMString {
|
||||
self.kind.clone()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-audiotrack-label
|
||||
fn Label(&self) -> DOMString {
|
||||
self.label.clone()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-audiotrack-language
|
||||
fn Language(&self) -> DOMString {
|
||||
self.language.clone()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-audiotrack-enabled
|
||||
fn Enabled(&self) -> bool {
|
||||
self.enabled()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-audiotrack-enabled
|
||||
fn SetEnabled(&self, value: bool) {
|
||||
self.set_enabled(value);
|
||||
}
|
||||
}
|
126
components/script/dom/audiotracklist.rs
Normal file
126
components/script/dom/audiotracklist.rs
Normal file
|
@ -0,0 +1,126 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::dom::audiotrack::AudioTrack;
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::AudioTrackListBinding::{self, AudioTrackListMethods};
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::refcounted::Trusted;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::eventtarget::EventTarget;
|
||||
use crate::dom::window::Window;
|
||||
use crate::task_source::TaskSource;
|
||||
use dom_struct::dom_struct;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct AudioTrackList {
|
||||
eventtarget: EventTarget,
|
||||
tracks: DomRefCell<Vec<Dom<AudioTrack>>>,
|
||||
}
|
||||
|
||||
impl AudioTrackList {
|
||||
pub fn new_inherited(tracks: &[&AudioTrack]) -> AudioTrackList {
|
||||
AudioTrackList {
|
||||
eventtarget: EventTarget::new_inherited(),
|
||||
tracks: DomRefCell::new(tracks.iter().map(|track| Dom::from_ref(&**track)).collect()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(window: &Window, tracks: &[&AudioTrack]) -> DomRoot<AudioTrackList> {
|
||||
reflect_dom_object(
|
||||
Box::new(AudioTrackList::new_inherited(tracks)),
|
||||
window,
|
||||
AudioTrackListBinding::Wrap,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.tracks.borrow().len()
|
||||
}
|
||||
|
||||
pub fn item(&self, idx: usize) -> Option<DomRoot<AudioTrack>> {
|
||||
self.tracks
|
||||
.borrow()
|
||||
.get(idx)
|
||||
.map(|track| DomRoot::from_ref(&**track))
|
||||
}
|
||||
|
||||
pub fn enabled_index(&self) -> Option<usize> {
|
||||
self.tracks
|
||||
.borrow()
|
||||
.iter()
|
||||
.position(|track| track.enabled())
|
||||
}
|
||||
|
||||
// TODO(#22799) Integrate DOM Audio and Video track selection with media player.
|
||||
pub fn set_enabled(&self, idx: usize, value: bool) {
|
||||
let track = match self.item(idx) {
|
||||
Some(t) => t,
|
||||
None => return,
|
||||
};
|
||||
|
||||
// If the chosen tracks enabled status is the same as the new status, return early.
|
||||
if track.enabled() == value {
|
||||
return;
|
||||
}
|
||||
// Set the tracks enabled status.
|
||||
track.set_enabled(value);
|
||||
|
||||
// Queue a task to fire an event named change.
|
||||
let global = &self.global();
|
||||
let this = Trusted::new(self);
|
||||
let (source, canceller) = global
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.media_element_task_source_with_canceller();
|
||||
|
||||
let _ = source.queue_with_canceller(
|
||||
task!(media_track_change: move || {
|
||||
let this = this.root();
|
||||
this.upcast::<EventTarget>().fire_event(atom!("change"));
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn add(&self, track: &AudioTrack) {
|
||||
self.tracks.borrow_mut().push(Dom::from_ref(track));
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
self.tracks.borrow_mut().clear();
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioTrackListMethods for AudioTrackList {
|
||||
// https://html.spec.whatwg.org/multipage/#dom-audiotracklist-length
|
||||
fn Length(&self) -> u32 {
|
||||
self.len() as u32
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-tracklist-item
|
||||
fn IndexedGetter(&self, idx: u32) -> Option<DomRoot<AudioTrack>> {
|
||||
self.item(idx as usize)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-audiotracklist-gettrackbyid
|
||||
fn GetTrackById(&self, id: DOMString) -> Option<DomRoot<AudioTrack>> {
|
||||
self.tracks
|
||||
.borrow()
|
||||
.iter()
|
||||
.find(|track| track.id() == id)
|
||||
.map(|track| DomRoot::from_ref(&**track))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#handler-tracklist-onchange
|
||||
event_handler!(change, GetOnchange, SetOnchange);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#handler-tracklist-onaddtrack
|
||||
event_handler!(addtrack, GetOnaddtrack, SetOnaddtrack);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#handler-tracklist-onremovetrack
|
||||
event_handler!(removetrack, GetOnremovetrack, SetOnremovetrack);
|
||||
}
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
use crate::document_loader::{LoadBlocker, LoadType};
|
||||
use crate::dom::attr::Attr;
|
||||
use crate::dom::audiotrack::AudioTrack;
|
||||
use crate::dom::audiotracklist::AudioTrackList;
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::CanPlayTypeResult;
|
||||
|
@ -15,6 +17,7 @@ use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethod
|
|||
use crate::dom::bindings::codegen::Bindings::TextTrackBinding::{TextTrackKind, TextTrackMode};
|
||||
use crate::dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId};
|
||||
use crate::dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId};
|
||||
use crate::dom::bindings::codegen::UnionTypes::VideoTrackOrAudioTrackOrTextTrack;
|
||||
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::num::Finite;
|
||||
|
@ -25,6 +28,7 @@ use crate::dom::bindings::str::{DOMString, USVString};
|
|||
use crate::dom::blob::Blob;
|
||||
use crate::dom::document::Document;
|
||||
use crate::dom::element::{AttributeMutation, Element};
|
||||
use crate::dom::event::Event;
|
||||
use crate::dom::eventtarget::EventTarget;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::htmlelement::HTMLElement;
|
||||
|
@ -37,6 +41,9 @@ use crate::dom::promise::Promise;
|
|||
use crate::dom::texttrack::TextTrack;
|
||||
use crate::dom::texttracklist::TextTrackList;
|
||||
use crate::dom::timeranges::{TimeRanges, TimeRangesContainer};
|
||||
use crate::dom::trackevent::TrackEvent;
|
||||
use crate::dom::videotrack::VideoTrack;
|
||||
use crate::dom::videotracklist::VideoTrackList;
|
||||
use crate::dom::virtualmethods::VirtualMethods;
|
||||
use crate::fetch::FetchCanceller;
|
||||
use crate::microtask::{Microtask, MicrotaskRunnable};
|
||||
|
@ -206,6 +213,10 @@ pub struct HTMLMediaElement {
|
|||
/// https://html.spec.whatwg.org/multipage/#dom-media-played
|
||||
#[ignore_malloc_size_of = "Rc"]
|
||||
played: DomRefCell<TimeRangesContainer>,
|
||||
// https://html.spec.whatwg.org/multipage/#dom-media-audiotracks
|
||||
audio_tracks_list: MutNullableDom<AudioTrackList>,
|
||||
// https://html.spec.whatwg.org/multipage/#dom-media-videotracks
|
||||
video_tracks_list: MutNullableDom<VideoTrackList>,
|
||||
/// https://html.spec.whatwg.org/multipage/#dom-media-texttracks
|
||||
text_tracks_list: MutNullableDom<TextTrackList>,
|
||||
/// Time of last timeupdate notification.
|
||||
|
@ -268,6 +279,8 @@ impl HTMLMediaElement {
|
|||
seeking: Cell::new(false),
|
||||
resource_url: DomRefCell::new(None),
|
||||
played: DomRefCell::new(TimeRangesContainer::new()),
|
||||
audio_tracks_list: Default::default(),
|
||||
video_tracks_list: Default::default(),
|
||||
text_tracks_list: Default::default(),
|
||||
next_timeupdate_event: Cell::new(time::get_time() + Duration::milliseconds(250)),
|
||||
current_fetch_context: DomRefCell::new(None),
|
||||
|
@ -803,7 +816,8 @@ impl HTMLMediaElement {
|
|||
)));
|
||||
|
||||
// Step 2.
|
||||
// FIXME(nox): Forget the media-resource-specific tracks.
|
||||
this.AudioTracks().clear();
|
||||
this.VideoTracks().clear();
|
||||
|
||||
// Step 3.
|
||||
this.network_state.set(NetworkState::NoSource);
|
||||
|
@ -904,7 +918,8 @@ impl HTMLMediaElement {
|
|||
// FIXME(nox): Detach MediaSource media provider object.
|
||||
|
||||
// Step 6.4.
|
||||
// FIXME(nox): Forget the media-resource-specific tracks.
|
||||
self.AudioTracks().clear();
|
||||
self.VideoTracks().clear();
|
||||
|
||||
// Step 6.5.
|
||||
if self.ready_state.get() != ReadyState::HaveNothing {
|
||||
|
@ -1227,6 +1242,92 @@ impl HTMLMediaElement {
|
|||
},
|
||||
PlayerEvent::MetadataUpdated(ref metadata) => {
|
||||
// https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list
|
||||
// => If the media resource is found to have an audio track
|
||||
if !metadata.audio_tracks.is_empty() {
|
||||
for (i, _track) in metadata.audio_tracks.iter().enumerate() {
|
||||
// Step 1.
|
||||
let kind = match i {
|
||||
0 => DOMString::from("main"),
|
||||
_ => DOMString::new(),
|
||||
};
|
||||
let window = window_from_node(self);
|
||||
let audio_track = AudioTrack::new(
|
||||
&window,
|
||||
DOMString::new(),
|
||||
kind,
|
||||
DOMString::new(),
|
||||
DOMString::new(),
|
||||
);
|
||||
|
||||
// Steps 2. & 3.
|
||||
self.AudioTracks().add(&audio_track);
|
||||
|
||||
// Step 4
|
||||
// https://www.w3.org/TR/media-frags/#media-fragment-syntax
|
||||
// https://github.com/servo/servo/issues/22366
|
||||
|
||||
// Step 5. & 6,
|
||||
if self.AudioTracks().enabled_index().is_none() {
|
||||
self.AudioTracks()
|
||||
.set_enabled(self.AudioTracks().len() - 1, true);
|
||||
}
|
||||
|
||||
// Steps 7.
|
||||
let event = TrackEvent::new(
|
||||
&self.global(),
|
||||
atom!("addtrack"),
|
||||
false,
|
||||
false,
|
||||
&Some(VideoTrackOrAudioTrackOrTextTrack::AudioTrack(audio_track)),
|
||||
);
|
||||
|
||||
event.upcast::<Event>().fire(self.upcast::<EventTarget>());
|
||||
}
|
||||
}
|
||||
|
||||
// => If the media resource is found to have a video track
|
||||
if !metadata.video_tracks.is_empty() {
|
||||
for (i, _track) in metadata.video_tracks.iter().enumerate() {
|
||||
// Step 1.
|
||||
let kind = match i {
|
||||
0 => DOMString::from("main"),
|
||||
_ => DOMString::new(),
|
||||
};
|
||||
let window = window_from_node(self);
|
||||
let video_track = VideoTrack::new(
|
||||
&window,
|
||||
DOMString::new(),
|
||||
kind,
|
||||
DOMString::new(),
|
||||
DOMString::new(),
|
||||
);
|
||||
|
||||
// Steps 2. & 3.
|
||||
self.VideoTracks().add(&video_track);
|
||||
|
||||
// Step 4.
|
||||
// https://www.w3.org/TR/media-frags/#media-fragment-syntax
|
||||
// https://github.com/servo/servo/issues/22366
|
||||
|
||||
// Step 5. & 6.
|
||||
if self.VideoTracks().selected_index().is_none() {
|
||||
self.VideoTracks()
|
||||
.set_selected(self.VideoTracks().len() - 1, true);
|
||||
}
|
||||
|
||||
// Steps 7.
|
||||
let event = TrackEvent::new(
|
||||
&self.global(),
|
||||
atom!("addtrack"),
|
||||
false,
|
||||
false,
|
||||
&Some(VideoTrackOrAudioTrackOrTextTrack::VideoTrack(video_track)),
|
||||
);
|
||||
|
||||
event.upcast::<Event>().fire(self.upcast::<EventTarget>());
|
||||
}
|
||||
}
|
||||
|
||||
// => "Once enough of the media data has been fetched to determine the duration..."
|
||||
// Step 1.
|
||||
// servo-media owns the media timeline.
|
||||
|
@ -1287,7 +1388,7 @@ impl HTMLMediaElement {
|
|||
// https://www.w3.org/TR/media-frags/#media-fragment-syntax
|
||||
// https://github.com/servo/media/issues/156
|
||||
|
||||
// XXX Steps 12 and 13 require audio and video tracks support.
|
||||
// Step 12 & 13 are already handled by the earlier media track processing.
|
||||
},
|
||||
PlayerEvent::NeedData => {
|
||||
// The player needs more data.
|
||||
|
@ -1702,6 +1803,20 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
|
|||
TimeRanges::new(self.global().as_window(), buffered)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-media-audiotracks
|
||||
fn AudioTracks(&self) -> DomRoot<AudioTrackList> {
|
||||
let window = window_from_node(self);
|
||||
self.audio_tracks_list
|
||||
.or_init(|| AudioTrackList::new(&window, &[]))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-media-videotracks
|
||||
fn VideoTracks(&self) -> DomRoot<VideoTrackList> {
|
||||
let window = window_from_node(self);
|
||||
self.video_tracks_list
|
||||
.or_init(|| VideoTrackList::new(&window, &[]))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-media-texttracks
|
||||
fn TextTracks(&self) -> DomRoot<TextTrackList> {
|
||||
let window = window_from_node(self);
|
||||
|
|
|
@ -225,6 +225,8 @@ pub mod audiolistener;
|
|||
pub mod audionode;
|
||||
pub mod audioparam;
|
||||
pub mod audioscheduledsourcenode;
|
||||
pub mod audiotrack;
|
||||
pub mod audiotracklist;
|
||||
pub mod baseaudiocontext;
|
||||
pub mod beforeunloadevent;
|
||||
pub mod bindings;
|
||||
|
@ -478,6 +480,7 @@ pub mod timeranges;
|
|||
pub mod touch;
|
||||
pub mod touchevent;
|
||||
pub mod touchlist;
|
||||
pub mod trackevent;
|
||||
pub mod transitionevent;
|
||||
pub mod treewalker;
|
||||
pub mod uievent;
|
||||
|
@ -488,6 +491,8 @@ pub mod userscripts;
|
|||
pub mod validation;
|
||||
pub mod validitystate;
|
||||
pub mod values;
|
||||
pub mod videotrack;
|
||||
pub mod videotracklist;
|
||||
pub mod virtualmethods;
|
||||
pub mod vrdisplay;
|
||||
pub mod vrdisplaycapabilities;
|
||||
|
|
|
@ -4,13 +4,18 @@
|
|||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::TextTrackListBinding::{self, TextTrackListMethods};
|
||||
use crate::dom::bindings::codegen::UnionTypes::VideoTrackOrAudioTrackOrTextTrack;
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::reflector::reflect_dom_object;
|
||||
use crate::dom::bindings::refcounted::Trusted;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::event::Event;
|
||||
use crate::dom::eventtarget::EventTarget;
|
||||
use crate::dom::texttrack::TextTrack;
|
||||
use crate::dom::trackevent::TrackEvent;
|
||||
use crate::dom::window::Window;
|
||||
use crate::task_source::TaskSource;
|
||||
use dom_struct::dom_struct;
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -56,8 +61,40 @@ impl TextTrackList {
|
|||
// Only add a track if it does not exist in the list
|
||||
if self.find(track).is_none() {
|
||||
self.dom_tracks.borrow_mut().push(Dom::from_ref(track));
|
||||
|
||||
let this = Trusted::new(self);
|
||||
let (source, canceller) = &self
|
||||
.global()
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.media_element_task_source_with_canceller();
|
||||
|
||||
let idx = match self.find(&track) {
|
||||
Some(t) => t,
|
||||
None => return,
|
||||
};
|
||||
self.upcast::<EventTarget>().fire_event(atom!("addtrack"));
|
||||
|
||||
let _ = source.queue_with_canceller(
|
||||
task!(track_event_queue: move || {
|
||||
let this = this.root();
|
||||
|
||||
if let Some(track) = this.item(idx) {
|
||||
let event = TrackEvent::new(
|
||||
&this.global(),
|
||||
atom!("addtrack"),
|
||||
false,
|
||||
false,
|
||||
&Some(VideoTrackOrAudioTrackOrTextTrack::TextTrack(
|
||||
DomRoot::from_ref(&track)
|
||||
)),
|
||||
);
|
||||
|
||||
event.upcast::<Event>().fire(this.upcast::<EventTarget>());
|
||||
}
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(#22314, dlrobertson) allow TextTracks to be
|
||||
|
|
114
components/script/dom/trackevent.rs
Normal file
114
components/script/dom/trackevent.rs
Normal file
|
@ -0,0 +1,114 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::dom::audiotrack::AudioTrack;
|
||||
use crate::dom::bindings::codegen::Bindings::EventBinding::EventBinding::EventMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::TrackEventBinding;
|
||||
use crate::dom::bindings::codegen::Bindings::TrackEventBinding::TrackEventMethods;
|
||||
use crate::dom::bindings::codegen::UnionTypes::VideoTrackOrAudioTrackOrTextTrack;
|
||||
use crate::dom::bindings::error::Fallible;
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::event::Event;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::texttrack::TextTrack;
|
||||
use crate::dom::videotrack::VideoTrack;
|
||||
use crate::dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use servo_atoms::Atom;
|
||||
|
||||
#[must_root]
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
enum MediaTrack {
|
||||
Video(Dom<VideoTrack>),
|
||||
Audio(Dom<AudioTrack>),
|
||||
Text(Dom<TextTrack>),
|
||||
}
|
||||
|
||||
#[dom_struct]
|
||||
pub struct TrackEvent {
|
||||
event: Event,
|
||||
track: Option<MediaTrack>,
|
||||
}
|
||||
|
||||
impl TrackEvent {
|
||||
#[allow(unrooted_must_root)]
|
||||
fn new_inherited(track: &Option<VideoTrackOrAudioTrackOrTextTrack>) -> TrackEvent {
|
||||
let media_track = match track {
|
||||
Some(VideoTrackOrAudioTrackOrTextTrack::VideoTrack(VideoTrack)) => {
|
||||
Some(MediaTrack::Video(Dom::from_ref(VideoTrack)))
|
||||
},
|
||||
Some(VideoTrackOrAudioTrackOrTextTrack::AudioTrack(AudioTrack)) => {
|
||||
Some(MediaTrack::Audio(Dom::from_ref(AudioTrack)))
|
||||
},
|
||||
Some(VideoTrackOrAudioTrackOrTextTrack::TextTrack(TextTrack)) => {
|
||||
Some(MediaTrack::Text(Dom::from_ref(TextTrack)))
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
TrackEvent {
|
||||
event: Event::new_inherited(),
|
||||
track: media_track,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
global: &GlobalScope,
|
||||
type_: Atom,
|
||||
bubbles: bool,
|
||||
cancelable: bool,
|
||||
track: &Option<VideoTrackOrAudioTrackOrTextTrack>,
|
||||
) -> DomRoot<TrackEvent> {
|
||||
let te = reflect_dom_object(
|
||||
Box::new(TrackEvent::new_inherited(&track)),
|
||||
global,
|
||||
TrackEventBinding::Wrap,
|
||||
);
|
||||
{
|
||||
let event = te.upcast::<Event>();
|
||||
event.init_event(type_, bubbles, cancelable);
|
||||
}
|
||||
te
|
||||
}
|
||||
|
||||
pub fn Constructor(
|
||||
window: &Window,
|
||||
type_: DOMString,
|
||||
init: &TrackEventBinding::TrackEventInit,
|
||||
) -> Fallible<DomRoot<TrackEvent>> {
|
||||
Ok(TrackEvent::new(
|
||||
&window.global(),
|
||||
Atom::from(type_),
|
||||
init.parent.bubbles,
|
||||
init.parent.cancelable,
|
||||
&init.track,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl TrackEventMethods for TrackEvent {
|
||||
// https://html.spec.whatwg.org/multipage/#dom-trackevent-track
|
||||
fn GetTrack(&self) -> Option<VideoTrackOrAudioTrackOrTextTrack> {
|
||||
match &self.track {
|
||||
Some(MediaTrack::Video(VideoTrack)) => Some(
|
||||
VideoTrackOrAudioTrackOrTextTrack::VideoTrack(DomRoot::from_ref(VideoTrack)),
|
||||
),
|
||||
Some(MediaTrack::Audio(AudioTrack)) => Some(
|
||||
VideoTrackOrAudioTrackOrTextTrack::AudioTrack(DomRoot::from_ref(AudioTrack)),
|
||||
),
|
||||
Some(MediaTrack::Text(TextTrack)) => Some(
|
||||
VideoTrackOrAudioTrackOrTextTrack::TextTrack(DomRoot::from_ref(TextTrack)),
|
||||
),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-istrusted
|
||||
fn IsTrusted(&self) -> bool {
|
||||
self.event.IsTrusted()
|
||||
}
|
||||
}
|
97
components/script/dom/videotrack.rs
Normal file
97
components/script/dom/videotrack.rs
Normal file
|
@ -0,0 +1,97 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::dom::bindings::codegen::Bindings::VideoTrackBinding::{self, VideoTrackMethods};
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||
use crate::dom::bindings::root::DomRoot;
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use std::cell::Cell;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct VideoTrack {
|
||||
reflector_: Reflector,
|
||||
id: DOMString,
|
||||
kind: DOMString,
|
||||
label: DOMString,
|
||||
language: DOMString,
|
||||
selected: Cell<bool>,
|
||||
}
|
||||
|
||||
impl VideoTrack {
|
||||
pub fn new_inherited(
|
||||
id: DOMString,
|
||||
kind: DOMString,
|
||||
label: DOMString,
|
||||
language: DOMString,
|
||||
) -> VideoTrack {
|
||||
VideoTrack {
|
||||
reflector_: Reflector::new(),
|
||||
id: id.into(),
|
||||
kind: kind.into(),
|
||||
label: label.into(),
|
||||
language: language.into(),
|
||||
selected: Cell::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
window: &Window,
|
||||
id: DOMString,
|
||||
kind: DOMString,
|
||||
label: DOMString,
|
||||
language: DOMString,
|
||||
) -> DomRoot<VideoTrack> {
|
||||
reflect_dom_object(
|
||||
Box::new(VideoTrack::new_inherited(id, kind, label, language)),
|
||||
window,
|
||||
VideoTrackBinding::Wrap,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn id(&self) -> DOMString {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
pub fn selected(&self) -> bool {
|
||||
self.selected.get().clone()
|
||||
}
|
||||
|
||||
pub fn set_selected(&self, value: bool) {
|
||||
self.selected.set(value);
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoTrackMethods for VideoTrack {
|
||||
// https://html.spec.whatwg.org/multipage/#dom-videotrack-id
|
||||
fn Id(&self) -> DOMString {
|
||||
self.id()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-videotrack-kind
|
||||
fn Kind(&self) -> DOMString {
|
||||
self.kind.clone()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-videotrack-label
|
||||
fn Label(&self) -> DOMString {
|
||||
self.label.clone()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-videotrack-language
|
||||
fn Language(&self) -> DOMString {
|
||||
self.language.clone()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-videotrack-selected
|
||||
fn Selected(&self) -> bool {
|
||||
self.selected()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-videotrack-selected
|
||||
fn SetSelected(&self, value: bool) {
|
||||
self.set_selected(value);
|
||||
}
|
||||
}
|
164
components/script/dom/videotracklist.rs
Normal file
164
components/script/dom/videotracklist.rs
Normal file
|
@ -0,0 +1,164 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::VideoTrackListBinding::{self, VideoTrackListMethods};
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::refcounted::Trusted;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||
use crate::dom::bindings::root::Dom;
|
||||
use crate::dom::bindings::root::DomRoot;
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::eventtarget::EventTarget;
|
||||
use crate::dom::videotrack::VideoTrack;
|
||||
use crate::dom::window::Window;
|
||||
use crate::task_source::TaskSource;
|
||||
use dom_struct::dom_struct;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct VideoTrackList {
|
||||
eventtarget: EventTarget,
|
||||
tracks: DomRefCell<Vec<Dom<VideoTrack>>>,
|
||||
}
|
||||
|
||||
impl VideoTrackList {
|
||||
pub fn new_inherited(tracks: &[&VideoTrack]) -> VideoTrackList {
|
||||
VideoTrackList {
|
||||
eventtarget: EventTarget::new_inherited(),
|
||||
tracks: DomRefCell::new(tracks.iter().map(|track| Dom::from_ref(&**track)).collect()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(window: &Window, tracks: &[&VideoTrack]) -> DomRoot<VideoTrackList> {
|
||||
reflect_dom_object(
|
||||
Box::new(VideoTrackList::new_inherited(tracks)),
|
||||
window,
|
||||
VideoTrackListBinding::Wrap,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.tracks.borrow().len()
|
||||
}
|
||||
|
||||
pub fn item(&self, idx: usize) -> Option<DomRoot<VideoTrack>> {
|
||||
self.tracks
|
||||
.borrow()
|
||||
.get(idx)
|
||||
.map(|track| DomRoot::from_ref(&**track))
|
||||
}
|
||||
|
||||
pub fn selected_index(&self) -> Option<usize> {
|
||||
self.tracks
|
||||
.borrow()
|
||||
.iter()
|
||||
.position(|track| track.selected())
|
||||
}
|
||||
|
||||
// TODO(#22799) Integrate DOM Audio and Video track selection with media player.
|
||||
pub fn set_selected(&self, idx: usize, value: bool) {
|
||||
let track = match self.item(idx) {
|
||||
Some(t) => t,
|
||||
None => return,
|
||||
};
|
||||
|
||||
// If the chosen tracks selected status is the same as the new status, return early.
|
||||
if track.selected() == value {
|
||||
return;
|
||||
}
|
||||
|
||||
let global = &self.global();
|
||||
let this = Trusted::new(self);
|
||||
let (source, canceller) = global
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.media_element_task_source_with_canceller();
|
||||
|
||||
if let Some(current) = self.selected_index() {
|
||||
if current != idx {
|
||||
self.tracks.borrow()[current].set_selected(false);
|
||||
track.set_selected(true);
|
||||
|
||||
let _ = source.queue_with_canceller(
|
||||
task!(media_track_change: move || {
|
||||
let this = this.root();
|
||||
this.upcast::<EventTarget>().fire_event(atom!("change"));
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
} else {
|
||||
self.tracks.borrow()[current].set_selected(false);
|
||||
|
||||
let _ = source.queue_with_canceller(
|
||||
task!(media_track_change: move || {
|
||||
let this = this.root();
|
||||
this.upcast::<EventTarget>().fire_event(atom!("change"));
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
track.set_selected(true);
|
||||
|
||||
let _ = source.queue_with_canceller(
|
||||
task!(media_track_change: move || {
|
||||
let this = this.root();
|
||||
this.upcast::<EventTarget>().fire_event(atom!("change"));
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&self, track: &VideoTrack) {
|
||||
self.tracks.borrow_mut().push(Dom::from_ref(track));
|
||||
if track.selected() {
|
||||
if let Some(idx) = self.selected_index() {
|
||||
self.set_selected(idx, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
self.tracks.borrow_mut().clear();
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoTrackListMethods for VideoTrackList {
|
||||
// https://html.spec.whatwg.org/multipage/#dom-videotracklist-length
|
||||
fn Length(&self) -> u32 {
|
||||
self.len() as u32
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-tracklist-item
|
||||
fn IndexedGetter(&self, idx: u32) -> Option<DomRoot<VideoTrack>> {
|
||||
self.item(idx as usize)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-videotracklist-gettrackbyid
|
||||
fn GetTrackById(&self, id: DOMString) -> Option<DomRoot<VideoTrack>> {
|
||||
self.tracks
|
||||
.borrow()
|
||||
.iter()
|
||||
.find(|track| track.id() == id)
|
||||
.map(|track| DomRoot::from_ref(&**track))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-videotrack-selected
|
||||
fn SelectedIndex(&self) -> i32 {
|
||||
if let Some(idx) = self.selected_index() {
|
||||
return idx as i32;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#handler-tracklist-onchange
|
||||
event_handler!(change, GetOnchange, SetOnchange);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#handler-tracklist-onaddtrack
|
||||
event_handler!(addtrack, GetOnaddtrack, SetOnaddtrack);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#handler-tracklist-onremovetrack
|
||||
event_handler!(removetrack, GetOnremovetrack, SetOnremovetrack);
|
||||
}
|
14
components/script/dom/webidls/AudioTrack.webidl
Normal file
14
components/script/dom/webidls/AudioTrack.webidl
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#audiotrack
|
||||
|
||||
[Exposed=Window]
|
||||
interface AudioTrack {
|
||||
readonly attribute DOMString id;
|
||||
readonly attribute DOMString kind;
|
||||
readonly attribute DOMString label;
|
||||
readonly attribute DOMString language;
|
||||
attribute boolean enabled;
|
||||
};
|
16
components/script/dom/webidls/AudioTrackList.webidl
Normal file
16
components/script/dom/webidls/AudioTrackList.webidl
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#audiotracklist
|
||||
|
||||
[Exposed=Window]
|
||||
interface AudioTrackList : EventTarget {
|
||||
readonly attribute unsigned long length;
|
||||
getter AudioTrack (unsigned long index);
|
||||
AudioTrack? getTrackById(DOMString id);
|
||||
|
||||
attribute EventHandler onchange;
|
||||
attribute EventHandler onaddtrack;
|
||||
attribute EventHandler onremovetrack;
|
||||
};
|
|
@ -59,8 +59,8 @@ interface HTMLMediaElement : HTMLElement {
|
|||
[CEReactions] attribute boolean defaultMuted;
|
||||
|
||||
// tracks
|
||||
// readonly attribute AudioTrackList audioTracks;
|
||||
// readonly attribute VideoTrackList videoTracks;
|
||||
readonly attribute AudioTrackList audioTracks;
|
||||
readonly attribute VideoTrackList videoTracks;
|
||||
readonly attribute TextTrackList textTracks;
|
||||
TextTrack addTextTrack(TextTrackKind kind, optional DOMString label = "", optional DOMString language = "");
|
||||
};
|
||||
|
|
15
components/script/dom/webidls/TrackEvent.webidl
Normal file
15
components/script/dom/webidls/TrackEvent.webidl
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#the-trackevent-interface
|
||||
|
||||
[Exposed=Window,
|
||||
Constructor(DOMString type, optional TrackEventInit eventInitDict)]
|
||||
interface TrackEvent : Event {
|
||||
readonly attribute (VideoTrack or AudioTrack or TextTrack)? track;
|
||||
};
|
||||
|
||||
dictionary TrackEventInit : EventInit {
|
||||
(VideoTrack or AudioTrack or TextTrack)? track = null;
|
||||
};
|
14
components/script/dom/webidls/VideoTrack.webidl
Normal file
14
components/script/dom/webidls/VideoTrack.webidl
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#videotrack
|
||||
|
||||
[Exposed=Window]
|
||||
interface VideoTrack {
|
||||
readonly attribute DOMString id;
|
||||
readonly attribute DOMString kind;
|
||||
readonly attribute DOMString label;
|
||||
readonly attribute DOMString language;
|
||||
attribute boolean selected;
|
||||
};
|
17
components/script/dom/webidls/VideoTrackList.webidl
Normal file
17
components/script/dom/webidls/VideoTrackList.webidl
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#videotracklist
|
||||
|
||||
[Exposed=Window]
|
||||
interface VideoTrackList : EventTarget {
|
||||
readonly attribute unsigned long length;
|
||||
getter VideoTrack (unsigned long index);
|
||||
VideoTrack? getTrackById(DOMString id);
|
||||
readonly attribute long selectedIndex;
|
||||
|
||||
attribute EventHandler onchange;
|
||||
attribute EventHandler onaddtrack;
|
||||
attribute EventHandler onremovetrack;
|
||||
};
|
|
@ -1068,10 +1068,10 @@
|
|||
expected: FAIL
|
||||
|
||||
[HTMLMediaElement interface: document.createElement("video") must inherit property "audioTracks" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: document.createElement("video") must inherit property "videoTracks" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: document.createElement("video") must inherit property "textTracks" with the proper type]
|
||||
expected: FAIL
|
||||
|
@ -1137,10 +1137,10 @@
|
|||
expected: FAIL
|
||||
|
||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "audioTracks" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "videoTracks" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "textTracks" with the proper type]
|
||||
expected: FAIL
|
||||
|
@ -1278,10 +1278,10 @@
|
|||
expected: FAIL
|
||||
|
||||
[HTMLMediaElement interface: new Audio() must inherit property "audioTracks" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: new Audio() must inherit property "videoTracks" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: new Audio() must inherit property "textTracks" with the proper type]
|
||||
expected: FAIL
|
||||
|
@ -1422,10 +1422,10 @@
|
|||
expected: FAIL
|
||||
|
||||
[HTMLMediaElement interface: attribute audioTracks]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: attribute videoTracks]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: attribute textTracks]
|
||||
expected: FAIL
|
||||
|
@ -1434,139 +1434,139 @@
|
|||
expected: FAIL
|
||||
|
||||
[AudioTrackList interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface object length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface object name]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: attribute length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: operation getTrackById(DOMString)]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: attribute onchange]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: attribute onaddtrack]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: attribute onremovetrack]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface object length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface object name]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: attribute id]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: attribute kind]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: attribute label]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: attribute language]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: attribute enabled]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface object length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface object name]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: attribute length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: operation getTrackById(DOMString)]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: attribute selectedIndex]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: attribute onchange]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: attribute onaddtrack]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: attribute onremovetrack]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface object length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface object name]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: attribute id]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: attribute kind]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: attribute label]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: attribute language]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: attribute selected]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TextTrackList interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
|
@ -1848,34 +1848,34 @@
|
|||
expected: FAIL
|
||||
|
||||
[TrackEvent interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface object length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface object name]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface: attribute track]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent must be primary interface of new TrackEvent("addtrack", {track:document.createElement("track").track})]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Stringification of new TrackEvent("addtrack", {track:document.createElement("track").track})]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "track" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMapElement interface: attribute name]
|
||||
expected: FAIL
|
||||
|
@ -6784,10 +6784,10 @@
|
|||
expected: FAIL
|
||||
|
||||
[HTMLMediaElement interface: document.createElement("video") must inherit property "audioTracks" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: document.createElement("video") must inherit property "videoTracks" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "srcObject" with the proper type]
|
||||
expected: FAIL
|
||||
|
@ -6808,10 +6808,10 @@
|
|||
expected: FAIL
|
||||
|
||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "audioTracks" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "videoTracks" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: new Audio() must inherit property "srcObject" with the proper type]
|
||||
expected: FAIL
|
||||
|
@ -6832,10 +6832,10 @@
|
|||
expected: FAIL
|
||||
|
||||
[HTMLMediaElement interface: new Audio() must inherit property "audioTracks" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: new Audio() must inherit property "videoTracks" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: attribute crossOrigin]
|
||||
expected: FAIL
|
||||
|
@ -6856,10 +6856,10 @@
|
|||
expected: FAIL
|
||||
|
||||
[HTMLMediaElement interface: attribute audioTracks]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMediaElement interface: attribute videoTracks]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[HTMLMapElement interface: attribute name]
|
||||
expected: FAIL
|
||||
|
@ -9408,139 +9408,139 @@
|
|||
expected: FAIL
|
||||
|
||||
[AudioTrackList interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface object length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface object name]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: attribute length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: operation getTrackById(DOMString)]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: attribute onchange]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: attribute onaddtrack]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrackList interface: attribute onremovetrack]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface object length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface object name]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: attribute id]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: attribute kind]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: attribute label]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: attribute language]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[AudioTrack interface: attribute enabled]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface object length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface object name]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: attribute length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: operation getTrackById(DOMString)]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: attribute selectedIndex]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: attribute onchange]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: attribute onaddtrack]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrackList interface: attribute onremovetrack]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface object length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface object name]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: attribute id]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: attribute kind]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: attribute label]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: attribute language]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[VideoTrack interface: attribute selected]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TextTrack interface: attribute inBandMetadataTrackDispatchType]
|
||||
expected: FAIL
|
||||
|
@ -9549,34 +9549,34 @@
|
|||
expected: FAIL
|
||||
|
||||
[TrackEvent interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface object length]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface object name]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface: attribute track]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent must be primary interface of new TrackEvent("addtrack", {track:document.createElement("track").track})]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Stringification of new TrackEvent("addtrack", {track:document.createElement("track").track})]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "track" with the proper type]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[ValidityState must be primary interface of document.createElement("input").validity]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[constructor.html]
|
||||
[TrackEvent constructor, two args]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[TrackEvent constructor, one arg]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[createEvent.html]
|
||||
[TrackEvent created with createEvent]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
|
|
|
@ -19557,7 +19557,7 @@
|
|||
"testharness"
|
||||
],
|
||||
"mozilla/interfaces.html": [
|
||||
"55cafc9995da83d48230eed5b5c3863d8cf173c9",
|
||||
"ab4ead5cfb5afc8b65cb71841e32ee46ec75318b",
|
||||
"testharness"
|
||||
],
|
||||
"mozilla/interfaces.js": [
|
||||
|
|
|
@ -22,6 +22,8 @@ test_interfaces([
|
|||
"AudioNode",
|
||||
"AudioParam",
|
||||
"AudioScheduledSourceNode",
|
||||
"AudioTrack",
|
||||
"AudioTrackList",
|
||||
"BaseAudioContext",
|
||||
"BeforeUnloadEvent",
|
||||
"BiquadFilterNode",
|
||||
|
@ -214,12 +216,15 @@ test_interfaces([
|
|||
"Touch",
|
||||
"TouchEvent",
|
||||
"TouchList",
|
||||
"TrackEvent",
|
||||
"TransitionEvent",
|
||||
"TreeWalker",
|
||||
"UIEvent",
|
||||
"URL",
|
||||
"URLSearchParams",
|
||||
"ValidityState",
|
||||
"VideoTrack",
|
||||
"VideoTrackList",
|
||||
"WebAssembly",
|
||||
"WebGLRenderingContext",
|
||||
"WebGLUniformLocation",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue