Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the basics of TextTrack #22392

Merged
merged 2 commits into from Dec 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions components/atoms/static_atoms.txt
@@ -1,6 +1,7 @@
DOMContentLoaded
abort
activate
addtrack
beforeunload
button
canplay
Expand Down Expand Up @@ -69,6 +70,7 @@ range
readystatechange
reftest-wait
rejectionhandled
removetrack
reset
resize
right
Expand Down
37 changes: 37 additions & 0 deletions components/script/dom/htmlmediaelement.rs
Expand Up @@ -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::MediaErrorBinding::MediaErrorConstants::*;
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::{HTMLMediaElementTypeId, NodeTypeId};
use crate::dom::bindings::error::{Error, ErrorResult};
Expand All @@ -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::performanceresourcetiming::InitiatorType;
use crate::dom::promise::Promise;
use crate::dom::texttrack::TextTrack;
use crate::dom::texttracklist::TextTrackList;
use crate::dom::timeranges::{TimeRanges, TimeRangesContainer};
use crate::dom::virtualmethods::VirtualMethods;
use crate::fetch::FetchCanceller;
Expand Down Expand Up @@ -191,6 +194,8 @@ pub struct HTMLMediaElement {
/// https://html.spec.whatwg.org/multipage/#dom-media-played
#[ignore_malloc_size_of = "Rc"]
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>
Expand Down Expand Up @@ -243,6 +248,7 @@ impl HTMLMediaElement {
seeking: Cell::new(false),
resource_url: DomRefCell::new(None),
played: Rc::new(DomRefCell::new(TimeRangesContainer::new())),
text_tracks_list: Default::default(),
}
}

Expand Down Expand Up @@ -1376,6 +1382,37 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
fn Played(&self) -> DomRoot<TimeRanges> {
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 {
Expand Down
4 changes: 4 additions & 0 deletions components/script/dom/mod.rs
Expand Up @@ -460,6 +460,10 @@ pub mod text;
pub mod textcontrol;
pub mod textdecoder;
pub mod textencoder;
pub mod texttrack;
pub mod texttrackcue;
pub mod texttrackcuelist;
pub mod texttracklist;
pub mod timeranges;
pub mod touch;
pub mod touchevent;
Expand Down
145 changes: 145 additions & 0 deletions components/script/dom/texttrack.rs
@@ -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);
}
111 changes: 111 additions & 0 deletions components/script/dom/texttrackcue.rs
@@ -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);
}