script: Create structures for TextTrack API

Fill out the basics for the WebIDLs for the following:

  - TextTrack
  - TextTrackCue
  - TextTrackCueList
  - TextTrackList
This commit is contained in:
Dan Robertson 2018-12-08 04:00:38 +00:00
parent 92962de76c
commit 62a9bfa0c5
No known key found for this signature in database
GPG key ID: 45C4A652C47E42A5
12 changed files with 571 additions and 2 deletions

View file

@ -1,6 +1,7 @@
DOMContentLoaded DOMContentLoaded
abort abort
activate activate
addtrack
beforeunload beforeunload
button button
canplay canplay
@ -69,6 +70,7 @@ range
readystatechange readystatechange
reftest-wait reftest-wait
rejectionhandled rejectionhandled
removetrack
reset reset
resize resize
right right

View file

@ -12,6 +12,7 @@ use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::HTMLMediaE
use crate::dom::bindings::codegen::Bindings::HTMLSourceElementBinding::HTMLSourceElementMethods; use crate::dom::bindings::codegen::Bindings::HTMLSourceElementBinding::HTMLSourceElementMethods;
use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorConstants::*; use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorConstants::*;
use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethods; use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethods;
use crate::dom::bindings::codegen::Bindings::TextTrackBinding::{TextTrackKind, TextTrackMode};
use crate::dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId}; use crate::dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId};
use crate::dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId}; use crate::dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId};
use crate::dom::bindings::error::{Error, ErrorResult}; use crate::dom::bindings::error::{Error, ErrorResult};
@ -33,6 +34,8 @@ use crate::dom::mediaerror::MediaError;
use crate::dom::node::{document_from_node, window_from_node, Node, NodeDamage, UnbindContext}; use crate::dom::node::{document_from_node, window_from_node, Node, NodeDamage, UnbindContext};
use crate::dom::performanceresourcetiming::InitiatorType; use crate::dom::performanceresourcetiming::InitiatorType;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::dom::texttrack::TextTrack;
use crate::dom::texttracklist::TextTrackList;
use crate::dom::timeranges::{TimeRanges, TimeRangesContainer}; use crate::dom::timeranges::{TimeRanges, TimeRangesContainer};
use crate::dom::virtualmethods::VirtualMethods; use crate::dom::virtualmethods::VirtualMethods;
use crate::fetch::FetchCanceller; use crate::fetch::FetchCanceller;
@ -191,6 +194,8 @@ pub struct HTMLMediaElement {
/// https://html.spec.whatwg.org/multipage/#dom-media-played /// https://html.spec.whatwg.org/multipage/#dom-media-played
#[ignore_malloc_size_of = "Rc"] #[ignore_malloc_size_of = "Rc"]
played: Rc<DomRefCell<TimeRangesContainer>>, played: Rc<DomRefCell<TimeRangesContainer>>,
/// https://html.spec.whatwg.org/multipage/#dom-media-texttracks
text_tracks_list: MutNullableDom<TextTrackList>,
} }
/// <https://html.spec.whatwg.org/multipage/#dom-media-networkstate> /// <https://html.spec.whatwg.org/multipage/#dom-media-networkstate>
@ -243,6 +248,7 @@ impl HTMLMediaElement {
seeking: Cell::new(false), seeking: Cell::new(false),
resource_url: DomRefCell::new(None), resource_url: DomRefCell::new(None),
played: Rc::new(DomRefCell::new(TimeRangesContainer::new())), played: Rc::new(DomRefCell::new(TimeRangesContainer::new())),
text_tracks_list: Default::default(),
} }
} }
@ -1376,6 +1382,37 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
fn Played(&self) -> DomRoot<TimeRanges> { fn Played(&self) -> DomRoot<TimeRanges> {
TimeRanges::new(self.global().as_window(), self.played.clone()) TimeRanges::new(self.global().as_window(), self.played.clone())
} }
// https://html.spec.whatwg.org/multipage/#dom-media-texttracks
fn TextTracks(&self) -> DomRoot<TextTrackList> {
let window = window_from_node(self);
self.text_tracks_list
.or_init(|| TextTrackList::new(&window, &[]))
}
// https://html.spec.whatwg.org/multipage/#dom-media-addtexttrack
fn AddTextTrack(
&self,
kind: TextTrackKind,
label: DOMString,
language: DOMString,
) -> DomRoot<TextTrack> {
let window = window_from_node(self);
// Step 1 & 2
// FIXME(#22314, dlrobertson) set the ready state to Loaded
let track = TextTrack::new(
&window,
"".into(),
kind,
label,
language,
TextTrackMode::Hidden,
);
// Step 3 & 4
self.TextTracks().add(&track);
// Step 5
DomRoot::from_ref(&track)
}
} }
impl VirtualMethods for HTMLMediaElement { impl VirtualMethods for HTMLMediaElement {

View file

@ -460,6 +460,10 @@ pub mod text;
pub mod textcontrol; pub mod textcontrol;
pub mod textdecoder; pub mod textdecoder;
pub mod textencoder; pub mod textencoder;
pub mod texttrack;
pub mod texttrackcue;
pub mod texttrackcuelist;
pub mod texttracklist;
pub mod timeranges; pub mod timeranges;
pub mod touch; pub mod touch;
pub mod touchevent; pub mod touchevent;

View file

@ -0,0 +1,145 @@
/* 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::TextTrackBinding::{
self, TextTrackKind, TextTrackMethods, TextTrackMode,
};
use crate::dom::bindings::error::{Error, ErrorResult};
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::DOMString;
use crate::dom::eventtarget::EventTarget;
use crate::dom::texttrackcue::TextTrackCue;
use crate::dom::texttrackcuelist::TextTrackCueList;
use crate::dom::window::Window;
use dom_struct::dom_struct;
use std::cell::Cell;
#[dom_struct]
pub struct TextTrack {
eventtarget: EventTarget,
kind: TextTrackKind,
label: String,
language: String,
id: String,
mode: Cell<TextTrackMode>,
cue_list: MutNullableDom<TextTrackCueList>,
}
impl TextTrack {
pub fn new_inherited(
id: DOMString,
kind: TextTrackKind,
label: DOMString,
language: DOMString,
mode: TextTrackMode,
) -> TextTrack {
TextTrack {
eventtarget: EventTarget::new_inherited(),
kind: kind,
label: label.into(),
language: language.into(),
id: id.into(),
mode: Cell::new(mode),
cue_list: Default::default(),
}
}
pub fn new(
window: &Window,
id: DOMString,
kind: TextTrackKind,
label: DOMString,
language: DOMString,
mode: TextTrackMode,
) -> DomRoot<TextTrack> {
reflect_dom_object(
Box::new(TextTrack::new_inherited(id, kind, label, language, mode)),
window,
TextTrackBinding::Wrap,
)
}
pub fn get_cues(&self) -> DomRoot<TextTrackCueList> {
self.cue_list
.or_init(|| TextTrackCueList::new(&self.global().as_window(), &[]))
}
pub fn id(&self) -> &str {
&self.id
}
}
impl TextTrackMethods for TextTrack {
// https://html.spec.whatwg.org/multipage/#dom-texttrack-kind
fn Kind(&self) -> TextTrackKind {
self.kind
}
// https://html.spec.whatwg.org/multipage/#dom-texttrack-label
fn Label(&self) -> DOMString {
DOMString::from(self.label.clone())
}
// https://html.spec.whatwg.org/multipage/#dom-texttrack-language
fn Language(&self) -> DOMString {
DOMString::from(self.language.clone())
}
// https://html.spec.whatwg.org/multipage/#dom-texttrack-id
fn Id(&self) -> DOMString {
DOMString::from(self.id.clone())
}
// https://html.spec.whatwg.org/multipage/#dom-texttrack-mode
fn Mode(&self) -> TextTrackMode {
self.mode.get()
}
// https://html.spec.whatwg.org/multipage/#dom-texttrack-mode
fn SetMode(&self, value: TextTrackMode) {
self.mode.set(value)
}
// https://html.spec.whatwg.org/multipage/#dom-texttrack-cues
fn GetCues(&self) -> Option<DomRoot<TextTrackCueList>> {
match self.Mode() {
TextTrackMode::Disabled => None,
_ => Some(self.get_cues()),
}
}
// https://html.spec.whatwg.org/multipage/#dom-texttrack-addcue
fn AddCue(&self, cue: &TextTrackCue) -> ErrorResult {
// FIXME(#22314, dlrobertson) add Step 1 & 2
// Step 3
if let Some(old_track) = cue.get_track() {
// gecko calls RemoveCue when the given cue
// has an associated track, but doesn't return
// the error from it, so we wont either.
if let Err(_) = old_track.RemoveCue(cue) {
warn!("Failed to remove cues for the added cue's text track");
}
}
// Step 4
self.get_cues().add(cue);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-texttrack-removecue
fn RemoveCue(&self, cue: &TextTrackCue) -> ErrorResult {
// Step 1
let cues = self.get_cues();
let index = match cues.find(cue) {
Some(i) => Ok(i),
None => Err(Error::NotFound),
}?;
// Step 2
cues.remove(index);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#handler-texttrack-oncuechange
event_handler!(oncuechange, GetOncuechange, SetOncuechange);
}

View file

@ -0,0 +1,111 @@
/* 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::TextTrackCueBinding::{self, TextTrackCueMethods};
use crate::dom::bindings::num::Finite;
use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::eventtarget::EventTarget;
use crate::dom::texttrack::TextTrack;
use crate::dom::window::Window;
use dom_struct::dom_struct;
use std::cell::Cell;
#[dom_struct]
pub struct TextTrackCue {
eventtarget: EventTarget,
id: DomRefCell<DOMString>,
track: Option<Dom<TextTrack>>,
start_time: Cell<f64>,
end_time: Cell<f64>,
pause_on_exit: Cell<bool>,
}
impl TextTrackCue {
// FIXME(#22314, dlrobertson) implement VTTCue.
#[allow(dead_code)]
pub fn new_inherited(id: DOMString, track: Option<&TextTrack>) -> TextTrackCue {
TextTrackCue {
eventtarget: EventTarget::new_inherited(),
id: DomRefCell::new(id),
track: track.map(Dom::from_ref),
start_time: Cell::new(0.),
end_time: Cell::new(0.),
pause_on_exit: Cell::new(false),
}
}
// FIXME(#22314, dlrobertson) implement VTTCue.
#[allow(dead_code)]
pub fn new(window: &Window, id: DOMString, track: Option<&TextTrack>) -> DomRoot<TextTrackCue> {
reflect_dom_object(
Box::new(TextTrackCue::new_inherited(id, track)),
window,
TextTrackCueBinding::Wrap,
)
}
pub fn id(&self) -> DOMString {
self.id.borrow().clone()
}
pub fn get_track(&self) -> Option<DomRoot<TextTrack>> {
self.track.as_ref().map(|t| DomRoot::from_ref(&**t))
}
}
impl TextTrackCueMethods for TextTrackCue {
// https://html.spec.whatwg.org/multipage/#dom-texttrackcue-id
fn Id(&self) -> DOMString {
self.id()
}
// https://html.spec.whatwg.org/multipage/#dom-texttrackcue-id
fn SetId(&self, value: DOMString) {
*self.id.borrow_mut() = value;
}
// https://html.spec.whatwg.org/multipage/#dom-texttrackcue-track
fn GetTrack(&self) -> Option<DomRoot<TextTrack>> {
self.get_track()
}
// https://html.spec.whatwg.org/multipage/#dom-texttrackcue-starttime
fn StartTime(&self) -> Finite<f64> {
Finite::wrap(self.start_time.get())
}
// https://html.spec.whatwg.org/multipage/#dom-texttrackcue-starttime
fn SetStartTime(&self, value: Finite<f64>) {
self.start_time.set(*value);
}
// https://html.spec.whatwg.org/multipage/#dom-texttrackcue-endtime
fn EndTime(&self) -> Finite<f64> {
Finite::wrap(self.end_time.get())
}
// https://html.spec.whatwg.org/multipage/#dom-texttrackcue-endtime
fn SetEndTime(&self, value: Finite<f64>) {
self.end_time.set(*value);
}
// https://html.spec.whatwg.org/multipage/#dom-texttrackcue-pauseonexit
fn PauseOnExit(&self) -> bool {
self.pause_on_exit.get()
}
// https://html.spec.whatwg.org/multipage/#dom-texttrackcue-pauseonexit
fn SetPauseOnExit(&self, value: bool) {
self.pause_on_exit.set(value);
}
// https://html.spec.whatwg.org/multipage/#handler-texttrackcue-onenter
event_handler!(onenter, GetOnenter, SetOnenter);
// https://html.spec.whatwg.org/multipage/#handler-texttrackcue-onexit
event_handler!(onexit, GetOnexit, SetOnexit);
}

View file

@ -0,0 +1,91 @@
/* 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::TextTrackCueListBinding::{
self, TextTrackCueListMethods,
};
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::texttrackcue::TextTrackCue;
use crate::dom::window::Window;
use dom_struct::dom_struct;
#[dom_struct]
pub struct TextTrackCueList {
reflector_: Reflector,
dom_cues: DomRefCell<Vec<Dom<TextTrackCue>>>,
}
impl TextTrackCueList {
pub fn new_inherited(cues: &[&TextTrackCue]) -> TextTrackCueList {
TextTrackCueList {
reflector_: Reflector::new(),
dom_cues: DomRefCell::new(cues.iter().map(|g| Dom::from_ref(&**g)).collect()),
}
}
pub fn new(window: &Window, cues: &[&TextTrackCue]) -> DomRoot<TextTrackCueList> {
reflect_dom_object(
Box::new(TextTrackCueList::new_inherited(cues)),
window,
TextTrackCueListBinding::Wrap,
)
}
pub fn item(&self, idx: usize) -> Option<DomRoot<TextTrackCue>> {
self.dom_cues
.borrow()
.get(idx)
.map(|t| DomRoot::from_ref(&**t))
}
pub fn find(&self, cue: &TextTrackCue) -> Option<usize> {
self.dom_cues
.borrow()
.iter()
.enumerate()
.filter(|(_, c)| **c == cue)
.next()
.map(|(i, _)| i)
}
pub fn add(&self, cue: &TextTrackCue) {
// Only add a cue if it does not exist in the list
if self.find(cue).is_none() {
self.dom_cues.borrow_mut().push(Dom::from_ref(cue));
}
}
pub fn remove(&self, idx: usize) {
self.dom_cues.borrow_mut().remove(idx);
}
}
impl TextTrackCueListMethods for TextTrackCueList {
// https://html.spec.whatwg.org/multipage/#dom-texttrackcuelist-length
fn Length(&self) -> u32 {
self.dom_cues.borrow().len() as u32
}
// https://html.spec.whatwg.org/multipage/#dom-texttrackcuelist-item
fn IndexedGetter(&self, idx: u32) -> Option<DomRoot<TextTrackCue>> {
self.item(idx as usize)
}
// https://html.spec.whatwg.org/multipage/#dom-texttrackcuelist-getcuebyid
fn GetCueById(&self, id: DOMString) -> Option<DomRoot<TextTrackCue>> {
if id.is_empty() {
None
} else {
self.dom_cues
.borrow()
.iter()
.filter(|cue| cue.id() == id)
.next()
.map(|t| DomRoot::from_ref(&**t))
}
}
}

View file

@ -0,0 +1,103 @@
/* 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::TextTrackListBinding::{self, TextTrackListMethods};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::eventtarget::EventTarget;
use crate::dom::texttrack::TextTrack;
use crate::dom::window::Window;
use dom_struct::dom_struct;
#[dom_struct]
pub struct TextTrackList {
eventtarget: EventTarget,
dom_tracks: DomRefCell<Vec<Dom<TextTrack>>>,
}
impl TextTrackList {
pub fn new_inherited(tracks: &[&TextTrack]) -> TextTrackList {
TextTrackList {
eventtarget: EventTarget::new_inherited(),
dom_tracks: DomRefCell::new(tracks.iter().map(|g| Dom::from_ref(&**g)).collect()),
}
}
pub fn new(window: &Window, tracks: &[&TextTrack]) -> DomRoot<TextTrackList> {
reflect_dom_object(
Box::new(TextTrackList::new_inherited(tracks)),
window,
TextTrackListBinding::Wrap,
)
}
pub fn item(&self, idx: usize) -> Option<DomRoot<TextTrack>> {
self.dom_tracks
.borrow()
.get(idx as usize)
.map(|t| DomRoot::from_ref(&**t))
}
pub fn find(&self, track: &TextTrack) -> Option<usize> {
self.dom_tracks
.borrow()
.iter()
.enumerate()
.filter(|(_, t)| **t == track)
.next()
.map(|(i, _)| i)
}
pub fn add(&self, track: &TextTrack) {
// 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));
};
self.upcast::<EventTarget>().fire_event(atom!("addtrack"));
}
// FIXME(#22314, dlrobertson) allow TextTracks to be
// removed from the TextTrackList.
#[allow(dead_code)]
pub fn remove(&self, idx: usize) {
self.dom_tracks.borrow_mut().remove(idx);
self.upcast::<EventTarget>()
.fire_event(atom!("removetrack"));
}
}
impl TextTrackListMethods for TextTrackList {
// https://html.spec.whatwg.org/multipage/#dom-texttracklist-length
fn Length(&self) -> u32 {
self.dom_tracks.borrow().len() as u32
}
// https://html.spec.whatwg.org/multipage/#dom-texttracklist-item
fn IndexedGetter(&self, idx: u32) -> Option<DomRoot<TextTrack>> {
self.item(idx as usize)
}
// https://html.spec.whatwg.org/multipage/#dom-texttracklist-gettrackbyid
fn GetTrackById(&self, id: DOMString) -> Option<DomRoot<TextTrack>> {
let id_str = String::from(id.clone());
self.dom_tracks
.borrow()
.iter()
.filter(|track| track.id() == &id_str)
.next()
.map(|t| DomRoot::from_ref(&**t))
}
// https://html.spec.whatwg.org/multipage/#handler-texttracklist-onchange
event_handler!(onchange, GetOnchange, SetOnchange);
// https://html.spec.whatwg.org/multipage/#handler-texttracklist-onaddtrack
event_handler!(onaddtrack, GetOnaddtrack, SetOnaddtrack);
// https://html.spec.whatwg.org/multipage/#handler-texttracklist-onremovetrack
event_handler!(onremovetrack, GetOnremovetrack, SetOnremovetrack);
}

View file

@ -61,6 +61,6 @@ interface HTMLMediaElement : HTMLElement {
// tracks // tracks
// readonly attribute AudioTrackList audioTracks; // readonly attribute AudioTrackList audioTracks;
// readonly attribute VideoTrackList videoTracks; // readonly attribute VideoTrackList videoTracks;
// readonly attribute TextTrackList textTracks; readonly attribute TextTrackList textTracks;
// TextTrack addTextTrack(TextTrackKind kind, optional DOMString label = "", optional DOMString language = ""); TextTrack addTextTrack(TextTrackKind kind, optional DOMString label = "", optional DOMString language = "");
}; };

View file

@ -0,0 +1,30 @@
/* 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/#texttrack
enum TextTrackMode { "disabled", "hidden", "showing" };
enum TextTrackKind { "subtitles", "captions", "descriptions", "chapters", "metadata" };
[Exposed=Window]
interface TextTrack : EventTarget {
readonly attribute TextTrackKind kind;
readonly attribute DOMString label;
readonly attribute DOMString language;
readonly attribute DOMString id;
// readonly attribute DOMString inBandMetadataTrackDispatchType;
attribute TextTrackMode mode;
readonly attribute TextTrackCueList? cues;
// readonly attribute TextTrackCueList? activeCues;
[Throws]
void addCue(TextTrackCue cue);
[Throws]
void removeCue(TextTrackCue cue);
attribute EventHandler oncuechange;
};

View file

@ -0,0 +1,18 @@
/* 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/#texttrackcue
[Exposed=Window]
interface TextTrackCue : EventTarget {
readonly attribute TextTrack? track;
attribute DOMString id;
attribute double startTime;
attribute double endTime;
attribute boolean pauseOnExit;
attribute EventHandler onenter;
attribute EventHandler onexit;
};

View file

@ -0,0 +1,12 @@
/* 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/#texttrackcuelist
[Exposed=Window]
interface TextTrackCueList {
readonly attribute unsigned long length;
getter TextTrackCue (unsigned long index);
TextTrackCue? getCueById(DOMString id);
};

View 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/#texttracklist
[Exposed=Window]
interface TextTrackList : EventTarget {
readonly attribute unsigned long length;
getter TextTrack (unsigned long index);
TextTrack? getTrackById(DOMString id);
attribute EventHandler onchange;
attribute EventHandler onaddtrack;
attribute EventHandler onremovetrack;
};