diff options
Diffstat (limited to 'Source/WebCore/html/track/TextTrack.cpp')
-rw-r--r-- | Source/WebCore/html/track/TextTrack.cpp | 436 |
1 files changed, 203 insertions, 233 deletions
diff --git a/Source/WebCore/html/track/TextTrack.cpp b/Source/WebCore/html/track/TextTrack.cpp index 52b57b32c..0445edcdb 100644 --- a/Source/WebCore/html/track/TextTrack.cpp +++ b/Source/WebCore/html/track/TextTrack.cpp @@ -1,6 +1,6 @@ /* - * Copyright (C) 2011 Google Inc. All rights reserved. - * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2013 Google Inc. All rights reserved. + * Copyright (C) 2011-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -30,130 +30,104 @@ */ #include "config.h" +#include "TextTrack.h" #if ENABLE(VIDEO_TRACK) -#include "TextTrack.h" - #include "Event.h" +#include "ExceptionCode.h" #include "HTMLMediaElement.h" #include "SourceBuffer.h" #include "TextTrackCueList.h" #include "TextTrackList.h" -#include "TextTrackRegionList.h" +#include "VTTRegion.h" +#include "VTTRegionList.h" namespace WebCore { -static const int invalidTrackIndex = -1; - const AtomicString& TextTrack::subtitlesKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, subtitles, ("subtitles", AtomicString::ConstructFromLiteral)); + static NeverDestroyed<const AtomicString> subtitles("subtitles", AtomicString::ConstructFromLiteral); return subtitles; } -const AtomicString& TextTrack::captionsKeyword() +static const AtomicString& captionsKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, captions, ("captions", AtomicString::ConstructFromLiteral)); + static NeverDestroyed<const AtomicString> captions("captions", AtomicString::ConstructFromLiteral); return captions; } -const AtomicString& TextTrack::descriptionsKeyword() +static const AtomicString& descriptionsKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, descriptions, ("descriptions", AtomicString::ConstructFromLiteral)); + static NeverDestroyed<const AtomicString> descriptions("descriptions", AtomicString::ConstructFromLiteral); return descriptions; } -const AtomicString& TextTrack::chaptersKeyword() +static const AtomicString& chaptersKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, chapters, ("chapters", AtomicString::ConstructFromLiteral)); + static NeverDestroyed<const AtomicString> chapters("chapters", AtomicString::ConstructFromLiteral); return chapters; } -const AtomicString& TextTrack::metadataKeyword() +static const AtomicString& metadataKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, metadata, ("metadata", AtomicString::ConstructFromLiteral)); + static NeverDestroyed<const AtomicString> metadata("metadata", AtomicString::ConstructFromLiteral); return metadata; } -const AtomicString& TextTrack::forcedKeyword() +static const AtomicString& forcedKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, forced, ("forced", AtomicString::ConstructFromLiteral)); + static NeverDestroyed<const AtomicString> forced("forced", AtomicString::ConstructFromLiteral); return forced; } -const AtomicString& TextTrack::disabledKeyword() -{ - DEFINE_STATIC_LOCAL(const AtomicString, open, ("disabled", AtomicString::ConstructFromLiteral)); - return open; -} - -const AtomicString& TextTrack::hiddenKeyword() -{ - DEFINE_STATIC_LOCAL(const AtomicString, closed, ("hidden", AtomicString::ConstructFromLiteral)); - return closed; -} - -const AtomicString& TextTrack::showingKeyword() -{ - DEFINE_STATIC_LOCAL(const AtomicString, ended, ("showing", AtomicString::ConstructFromLiteral)); - return ended; -} - TextTrack* TextTrack::captionMenuOffItem() { - static TextTrack* off = TextTrack::create(0, 0, "off menu item", "", "", "").leakRef(); - return off; + static TextTrack& off = TextTrack::create(nullptr, nullptr, "off menu item", emptyAtom, emptyAtom, emptyAtom).leakRef(); + return &off; } TextTrack* TextTrack::captionMenuAutomaticItem() { - static TextTrack* automatic = TextTrack::create(0, 0, "automatic menu item", "", "", "").leakRef(); - return automatic; + static TextTrack& automatic = TextTrack::create(nullptr, nullptr, "automatic menu item", emptyAtom, emptyAtom, emptyAtom).leakRef(); + return &automatic; } TextTrack::TextTrack(ScriptExecutionContext* context, TextTrackClient* client, const AtomicString& kind, const AtomicString& id, const AtomicString& label, const AtomicString& language, TextTrackType type) : TrackBase(TrackBase::TextTrack, id, label, language) - , m_cues(0) , m_scriptExecutionContext(context) -#if ENABLE(WEBVTT_REGIONS) - , m_regions(0) -#endif - , m_mode(disabledKeyword().string()) , m_client(client) , m_trackType(type) - , m_readinessState(NotLoaded) - , m_trackIndex(invalidTrackIndex) - , m_renderedTrackIndex(invalidTrackIndex) - , m_hasBeenConfigured(false) { - setKindInternal(kind); + if (kind == captionsKeyword()) + m_kind = Kind::Captions; + else if (kind == chaptersKeyword()) + m_kind = Kind::Chapters; + else if (kind == descriptionsKeyword()) + m_kind = Kind::Descriptions; + else if (kind == forcedKeyword()) + m_kind = Kind::Forced; + else if (kind == metadataKeyword()) + m_kind = Kind::Metadata; } TextTrack::~TextTrack() { if (m_cues) { if (m_client) - m_client->textTrackRemoveCues(this, m_cues.get()); - + m_client->textTrackRemoveCues(*this, *m_cues); for (size_t i = 0; i < m_cues->length(); ++i) - m_cues->item(i)->setTrack(0); -#if ENABLE(WEBVTT_REGIONS) + m_cues->item(i)->setTrack(nullptr); + } + if (m_regions) { for (size_t i = 0; i < m_regions->length(); ++i) - m_regions->item(i)->setTrack(0); -#endif + m_regions->item(i)->setTrack(nullptr); } - clearClient(); -} - -bool TextTrack::isValidKind(const AtomicString& value) const -{ - return TextTrack::isValidKindKeyword(value); } bool TextTrack::enabled() const { - return m_mode != disabledKeyword(); + return m_mode != Mode::Disabled; } bool TextTrack::isValidKindKeyword(const AtomicString& value) @@ -174,60 +148,102 @@ bool TextTrack::isValidKindKeyword(const AtomicString& value) return false; } -void TextTrack::setKind(const AtomicString& newKind) +const AtomicString& TextTrack::kindKeyword() const +{ + switch (m_kind) { + case Kind::Captions: + return captionsKeyword(); + case Kind::Chapters: + return chaptersKeyword(); + case Kind::Descriptions: + return descriptionsKeyword(); + case Kind::Forced: + return forcedKeyword(); + case Kind::Metadata: + return metadataKeyword(); + case Kind::Subtitles: + return subtitlesKeyword(); + } + ASSERT_NOT_REACHED(); + return subtitlesKeyword(); +} + +void TextTrack::setKind(Kind newKind) { - String oldKind = kind(); + auto oldKind = m_kind; -#if ENABLE(MEDIA_SOURCE) // 10.1 kind, on setting: // 1. If the value being assigned to this attribute does not match one of the text track kinds, // then abort these steps. - if (!isValidKindKeyword(newKind)) - return; // 2. Update this attribute to the new value. - setKindInternal(newKind); + m_kind = newKind; +#if ENABLE(MEDIA_SOURCE) // 3. If the sourceBuffer attribute on this track is not null, then queue a task to fire a simple // event named change at sourceBuffer.textTracks. if (m_sourceBuffer) - m_sourceBuffer->textTracks()->scheduleChangeEvent(); + m_sourceBuffer->textTracks().scheduleChangeEvent(); // 4. Queue a task to fire a simple event named change at the TextTrackList object referenced by // the textTracks attribute on the HTMLMediaElement. if (mediaElement()) - mediaElement()->textTracks()->scheduleChangeEvent(); -#else - TrackBase::setKind(newKind); + mediaElement()->textTracks().scheduleChangeEvent(); #endif - if (m_client && oldKind != kind()) - m_client->textTrackKindChanged(this); + if (m_client && oldKind != m_kind) + m_client->textTrackKindChanged(*this); } -void TextTrack::setMode(const AtomicString& mode) +void TextTrack::setKindKeywordIgnoringASCIICase(StringView keyword) { - // On setting, if the new value isn't equal to what the attribute would currently - // return, the new value must be processed as follows ... - if (mode != disabledKeyword() && mode != hiddenKeyword() && mode != showingKeyword()) + if (keyword.isNull()) { + // The missing value default is the subtitles state. + setKind(Kind::Subtitles); return; + } + if (equalLettersIgnoringASCIICase(keyword, "captions")) + setKind(Kind::Captions); + else if (equalLettersIgnoringASCIICase(keyword, "chapters")) + setKind(Kind::Chapters); + else if (equalLettersIgnoringASCIICase(keyword, "descriptions")) + setKind(Kind::Descriptions); + else if (equalLettersIgnoringASCIICase(keyword, "forced")) + setKind(Kind::Forced); + else if (equalLettersIgnoringASCIICase(keyword, "metadata")) + setKind(Kind::Metadata); + else if (equalLettersIgnoringASCIICase(keyword, "subtitles")) + setKind(Kind::Subtitles); + else { + // The invalid value default is the metadata state. + setKind(Kind::Metadata); + } +} +void TextTrack::setMode(Mode mode) +{ + // On setting, if the new value isn't equal to what the attribute would currently + // return, the new value must be processed as follows ... if (m_mode == mode) return; // If mode changes to disabled, remove this track's cues from the client // because they will no longer be accessible from the cues() function. - if (mode == disabledKeyword() && m_client && m_cues) - m_client->textTrackRemoveCues(this, m_cues.get()); - - if (mode != showingKeyword() && m_cues) - for (size_t i = 0; i < m_cues->length(); ++i) - m_cues->item(i)->removeDisplayTree(); + if (mode == Mode::Disabled && m_client && m_cues) + m_client->textTrackRemoveCues(*this, *m_cues); + + if (mode != Mode::Showing && m_cues) { + for (size_t i = 0; i < m_cues->length(); ++i) { + TextTrackCue* cue = m_cues->item(i); + if (cue->isRenderable()) + toVTTCue(cue)->removeDisplayTree(); + } + } m_mode = mode; if (m_client) - m_client->textTrackModeChanged(this); + m_client->textTrackModeChanged(*this); } TextTrackCueList* TextTrack::cues() @@ -237,9 +253,9 @@ TextTrackCueList* TextTrack::cues() // Otherwise, it must return null. When an object is returned, the // same object must be returned each time. // http://www.whatwg.org/specs/web-apps/current-work/#dom-texttrack-cues - if (m_mode != disabledKeyword()) - return ensureTextTrackCueList(); - return 0; + if (m_mode == Mode::Disabled) + return nullptr; + return &ensureTextTrackCueList(); } void TextTrack::removeAllCues() @@ -248,12 +264,12 @@ void TextTrack::removeAllCues() return; if (m_client) - m_client->textTrackRemoveCues(this, m_cues.get()); + m_client->textTrackRemoveCues(*this, *m_cues); for (size_t i = 0; i < m_cues->length(); ++i) - m_cues->item(i)->setTrack(0); + m_cues->item(i)->setTrack(nullptr); - m_cues = 0; + m_cues = nullptr; } TextTrackCueList* TextTrack::activeCues() const @@ -264,145 +280,136 @@ TextTrackCueList* TextTrack::activeCues() const // order. Otherwise, it must return null. When an object is returned, the // same object must be returned each time. // http://www.whatwg.org/specs/web-apps/current-work/#dom-texttrack-activecues - if (m_cues && m_mode != disabledKeyword()) - return m_cues->activeCues(); - return 0; + if (!m_cues || m_mode == Mode::Disabled) + return nullptr; + return &m_cues->activeCues(); } -void TextTrack::addCue(PassRefPtr<TextTrackCue> prpCue) +ExceptionOr<void> TextTrack::addCue(Ref<TextTrackCue>&& cue) { - if (!prpCue) - return; - - RefPtr<TextTrackCue> cue = prpCue; + // 4.7.10.12.6 Text tracks exposing in-band metadata + // The UA will use DataCue to expose only text track cue objects that belong to a text track that has a text + // track kind of metadata. + // If a DataCue is added to a TextTrack via the addCue() method but the text track does not have its text + // track kind set to metadata, throw a InvalidNodeTypeError exception and don't add the cue to the TextTrackList + // of the TextTrack. + if (cue->cueType() == TextTrackCue::Data && m_kind != Kind::Metadata) + return Exception { INVALID_NODE_TYPE_ERR }; // TODO(93143): Add spec-compliant behavior for negative time values. - if (std::isnan(cue->startTime()) || std::isnan(cue->endTime()) || cue->startTime() < 0 || cue->endTime() < 0) - return; + if (!cue->startMediaTime().isValid() || !cue->endMediaTime().isValid() || cue->startMediaTime() < MediaTime::zeroTime() || cue->endMediaTime() < MediaTime::zeroTime()) + return { }; // 4.8.10.12.5 Text track API // The addCue(cue) method of TextTrack objects, when invoked, must run the following steps: + auto* cueTrack = cue->track(); + if (cueTrack == this) + return { }; + // 1. If the given cue is in a text track list of cues, then remove cue from that text track // list of cues. - TextTrack* cueTrack = cue->track(); - if (cueTrack && cueTrack != this) - cueTrack->removeCue(cue.get(), ASSERT_NO_EXCEPTION); + if (cueTrack) + cueTrack->removeCue(cue.get()); // 2. Add cue to the method's TextTrack object's text track's text track list of cues. cue->setTrack(this); - ensureTextTrackCueList()->add(cue); + ensureTextTrackCueList().add(cue.copyRef()); if (m_client) - m_client->textTrackAddCue(this, cue.get()); + m_client->textTrackAddCue(*this, cue); + + return { }; } -void TextTrack::removeCue(TextTrackCue* cue, ExceptionCode& ec) +ExceptionOr<void> TextTrack::removeCue(TextTrackCue& cue) { - if (!cue) - return; - // 4.8.10.12.5 Text track API // The removeCue(cue) method of TextTrack objects, when invoked, must run the following steps: // 1. If the given cue is not currently listed in the method's TextTrack // object's text track's text track list of cues, then throw a NotFoundError exception. - if (cue->track() != this) { - ec = NOT_FOUND_ERR; - return; - } + if (cue.track() != this) + return Exception { NOT_FOUND_ERR }; + if (!m_cues) + return Exception { INVALID_STATE_ERR }; // 2. Remove cue from the method's TextTrack object's text track's text track list of cues. - if (!m_cues || !m_cues->remove(cue)) { - ec = INVALID_STATE_ERR; - return; - } - - cue->setTrack(0); + m_cues->remove(cue); + cue.setIsActive(false); + cue.setTrack(nullptr); if (m_client) - m_client->textTrackRemoveCue(this, cue); -} + m_client->textTrackRemoveCue(*this, cue); -#if ENABLE(VIDEO_TRACK) && ENABLE(WEBVTT_REGIONS) -TextTrackRegionList* TextTrack::regionList() -{ - return ensureTextTrackRegionList(); + return { }; } -TextTrackRegionList* TextTrack::ensureTextTrackRegionList() +VTTRegionList& TextTrack::ensureVTTRegionList() { if (!m_regions) - m_regions = TextTrackRegionList::create(); + m_regions = VTTRegionList::create(); - return m_regions.get(); + return *m_regions; } -TextTrackRegionList* TextTrack::regions() +VTTRegionList* TextTrack::regions() { // If the text track mode of the text track that the TextTrack object // represents is not the text track disabled mode, then the regions - // attribute must return a live TextTrackRegionList object that represents + // attribute must return a live VTTRegionList object that represents // the text track list of regions of the text track. Otherwise, it must // return null. When an object is returned, the same object must be returned // each time. - if (m_mode != disabledKeyword()) - return ensureTextTrackRegionList(); - - return 0; + if (m_mode == Mode::Disabled) + return nullptr; + return &ensureVTTRegionList(); } -void TextTrack::addRegion(PassRefPtr<TextTrackRegion> prpRegion) +void TextTrack::addRegion(RefPtr<VTTRegion>&& region) { - if (!prpRegion) + if (!region) return; - RefPtr<TextTrackRegion> region = prpRegion; - TextTrackRegionList* regionList = ensureTextTrackRegionList(); + auto& regionList = ensureVTTRegionList(); // 1. If the given region is in a text track list of regions, then remove // region from that text track list of regions. - TextTrack* regionTrack = region->track(); + auto* regionTrack = region->track(); if (regionTrack && regionTrack != this) - regionTrack->removeRegion(region.get(), ASSERT_NO_EXCEPTION); + regionTrack->removeRegion(region.get()); // 2. If the method's TextTrack object's text track list of regions contains // a region with the same identifier as region replace the values of that // region's width, height, anchor point, viewport anchor point and scroll // attributes with those of region. - TextTrackRegion* existingRegion = regionList->getRegionById(region->id()); + auto* existingRegion = regionList.getRegionById(region->id()); if (existingRegion) { - existingRegion->updateParametersFromRegion(region.get()); + existingRegion->updateParametersFromRegion(*region); return; } - // Otherwise: add region to the method's TextTrack object's text track - // list of regions. + // Otherwise: add region to the method's TextTrack object's text track list of regions. region->setTrack(this); - regionList->add(region); + regionList.add(region.releaseNonNull()); } -void TextTrack::removeRegion(TextTrackRegion* region, ExceptionCode &ec) +ExceptionOr<void> TextTrack::removeRegion(VTTRegion* region) { if (!region) - return; + return { }; // 1. If the given region is not currently listed in the method's TextTrack // object's text track list of regions, then throw a NotFoundError exception. - if (region->track() != this) { - ec = NOT_FOUND_ERR; - return; - } - - if (!m_regions || !m_regions->remove(region)) { - ec = INVALID_STATE_ERR; - return; - } + if (region->track() != this) + return Exception { NOT_FOUND_ERR }; - region->setTrack(0); + ASSERT(m_regions); + m_regions->remove(*region); + region->setTrack(nullptr); + return { }; } -#endif void TextTrack::cueWillChange(TextTrackCue* cue) { @@ -411,7 +418,7 @@ void TextTrack::cueWillChange(TextTrackCue* cue) // The cue may need to be repositioned in the media element's interval tree, may need to // be re-rendered, etc, so remove it before the modification... - m_client->textTrackRemoveCue(this, cue); + m_client->textTrackRemoveCue(*this, *cue); } void TextTrack::cueDidChange(TextTrackCue* cue) @@ -420,60 +427,50 @@ void TextTrack::cueDidChange(TextTrackCue* cue) return; // Make sure the TextTrackCueList order is up-to-date. - ensureTextTrackCueList()->updateCueIndex(cue); + ensureTextTrackCueList().updateCueIndex(*cue); // ... and add it back again. - m_client->textTrackAddCue(this, cue); + m_client->textTrackAddCue(*this, *cue); } int TextTrack::trackIndex() { ASSERT(m_mediaElement); - - if (m_trackIndex == invalidTrackIndex) - m_trackIndex = m_mediaElement->textTracks()->getTrackIndex(this); - - return m_trackIndex; + if (!m_trackIndex) + m_trackIndex = m_mediaElement->textTracks().getTrackIndex(*this); + return m_trackIndex.value(); } void TextTrack::invalidateTrackIndex() { - m_trackIndex = invalidTrackIndex; - m_renderedTrackIndex = invalidTrackIndex; + m_trackIndex = std::nullopt; + m_renderedTrackIndex = std::nullopt; } bool TextTrack::isRendered() { - if (kind() != captionsKeyword() && kind() != subtitlesKeyword() && kind() != forcedKeyword()) - return false; - - if (m_mode != showingKeyword()) - return false; - - return true; + return (m_kind == Kind::Captions || m_kind == Kind::Subtitles || m_kind == Kind::Forced) + && m_mode == Mode::Showing; } -TextTrackCueList* TextTrack::ensureTextTrackCueList() +TextTrackCueList& TextTrack::ensureTextTrackCueList() { if (!m_cues) m_cues = TextTrackCueList::create(); - - return m_cues.get(); + return *m_cues; } int TextTrack::trackIndexRelativeToRenderedTracks() { ASSERT(m_mediaElement); - - if (m_renderedTrackIndex == invalidTrackIndex) - m_renderedTrackIndex = m_mediaElement->textTracks()->getTrackIndexRelativeToRenderedTracks(this); - - return m_renderedTrackIndex; + if (!m_renderedTrackIndex) + m_renderedTrackIndex = m_mediaElement->textTracks().getTrackIndexRelativeToRenderedTracks(*this); + return m_renderedTrackIndex.value(); } bool TextTrack::hasCue(TextTrackCue* cue, TextTrackCue::CueMatchRules match) { - if (cue->startTime() < 0 || cue->endTime() < 0) + if (cue->startMediaTime() < MediaTime::zeroTime() || cue->endMediaTime() < MediaTime::zeroTime()) return false; if (!m_cues || !m_cues->length()) @@ -495,7 +492,7 @@ bool TextTrack::hasCue(TextTrackCue* cue, TextTrackCue::CueMatchRules match) // If there is more than one cue with the same start time, back up to first one so we // consider all of them. - while (searchStart >= 2 && cue->startTime() == m_cues->item(searchStart - 2)->startTime()) + while (searchStart >= 2 && cue->hasEquivalentStartTime(*m_cues->item(searchStart - 2))) --searchStart; bool firstCompare = true; @@ -507,19 +504,20 @@ bool TextTrack::hasCue(TextTrackCue* cue, TextTrackCue::CueMatchRules match) return false; existingCue = m_cues->item(searchStart - 1); - if (!existingCue || cue->startTime() > existingCue->startTime()) + if (!existingCue) return false; - if (!existingCue->isEqual(*cue, match)) - continue; - - return true; + if (cue->startMediaTime() > (existingCue->startMediaTime() + startTimeVariance())) + return false; + + if (existingCue->isEqual(*cue, match)) + return true; } } size_t index = (searchStart + searchEnd) / 2; existingCue = m_cues->item(index); - if (cue->startTime() < existingCue->startTime() || (match != TextTrackCue::IgnoreDuration && cue->startTime() == existingCue->startTime() && cue->endTime() > existingCue->endTime())) + if ((cue->startMediaTime() + startTimeVariance()) < existingCue->startMediaTime() || (match != TextTrackCue::IgnoreDuration && cue->hasEquivalentStartTime(*existingCue) && cue->endMediaTime() > existingCue->endMediaTime())) searchEnd = index; else searchStart = index + 1; @@ -529,58 +527,29 @@ bool TextTrack::hasCue(TextTrackCue* cue, TextTrackCue::CueMatchRules match) return false; } -#if USE(PLATFORM_TEXT_TRACK_MENU) -PassRefPtr<PlatformTextTrack> TextTrack::platformTextTrack() -{ - static int uniqueId = 0; - - if (m_platformTextTrack) - return m_platformTextTrack; - - PlatformTextTrack::TrackKind platformKind = PlatformTextTrack::Caption; - if (kind() == subtitlesKeyword()) - platformKind = PlatformTextTrack::Subtitle; - else if (kind() == captionsKeyword()) - platformKind = PlatformTextTrack::Caption; - else if (kind() == descriptionsKeyword()) - platformKind = PlatformTextTrack::Description; - else if (kind() == chaptersKeyword()) - platformKind = PlatformTextTrack::Chapter; - else if (kind() == metadataKeyword()) - platformKind = PlatformTextTrack::MetaData; - else if (kind() == forcedKeyword()) - platformKind = PlatformTextTrack::Forced; - - PlatformTextTrack::TrackType type = PlatformTextTrack::OutOfBand; - if (m_trackType == TrackElement) - type = PlatformTextTrack::OutOfBand; - else if (m_trackType == AddTrack) - type = PlatformTextTrack::Script; - else if (m_trackType == InBand) - type = PlatformTextTrack::InBand; - - m_platformTextTrack = PlatformTextTrack::create(this, label(), language(), platformKind, type, ++uniqueId); - - return m_platformTextTrack; -} -#endif - bool TextTrack::isMainProgramContent() const { // "Main program" content is intrinsic to the presentation of the media file, regardless of locale. Content such as // directors commentary is not "main program" because it is not essential for the presentation. HTML5 doesn't have // a way to express this in a machine-reable form, it is typically done with the track label, so we assume that caption // tracks are main content and all other track types are not. - return kind() == captionsKeyword(); + return m_kind == Kind::Captions; +} + +bool TextTrack::containsOnlyForcedSubtitles() const +{ + return m_kind == Kind::Forced; } #if ENABLE(MEDIA_SOURCE) + void TextTrack::setLanguage(const AtomicString& language) { // 11.1 language, on setting: // 1. If the value being assigned to this attribute is not an empty string or a BCP 47 language // tag[BCP47], then abort these steps. - // FIXME(123926): Validate the BCP47-ness of langague. + // BCP 47 validation is done in TrackBase::setLanguage() which is + // shared between all tracks that support setting language. // 2. Update this attribute to the new value. TrackBase::setLanguage(language); @@ -588,13 +557,14 @@ void TextTrack::setLanguage(const AtomicString& language) // 3. If the sourceBuffer attribute on this track is not null, then queue a task to fire a simple // event named change at sourceBuffer.textTracks. if (m_sourceBuffer) - m_sourceBuffer->textTracks()->scheduleChangeEvent(); + m_sourceBuffer->textTracks().scheduleChangeEvent(); // 4. Queue a task to fire a simple event named change at the TextTrackList object referenced by // the textTracks attribute on the HTMLMediaElement. if (mediaElement()) - mediaElement()->textTracks()->scheduleChangeEvent(); + mediaElement()->textTracks().scheduleChangeEvent(); } + #endif } // namespace WebCore |