tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TextTrackCue.cpp (8047B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "mozilla/dom/TextTrackCue.h"
      7 
      8 #include "mozilla/ClearOnShutdown.h"
      9 #include "mozilla/dom/Document.h"
     10 #include "mozilla/dom/HTMLTrackElement.h"
     11 #include "mozilla/dom/TextTrackList.h"
     12 #include "mozilla/dom/TextTrackRegion.h"
     13 #include "mozilla/intl/Bidi.h"
     14 #include "nsComponentManagerUtils.h"
     15 #include "nsGlobalWindowInner.h"
     16 
     17 extern mozilla::LazyLogModule gTextTrackLog;
     18 
     19 #define LOG(msg, ...)                     \
     20  MOZ_LOG(gTextTrackLog, LogLevel::Debug, \
     21          ("TextTrackCue=%p, " msg, this, ##__VA_ARGS__))
     22 
     23 namespace mozilla::dom {
     24 
     25 NS_IMPL_CYCLE_COLLECTION_INHERITED(TextTrackCue, DOMEventTargetHelper,
     26                                   mDocument, mTrack, mTrackElement,
     27                                   mDisplayState, mRegion)
     28 
     29 NS_IMPL_ADDREF_INHERITED(TextTrackCue, DOMEventTargetHelper)
     30 NS_IMPL_RELEASE_INHERITED(TextTrackCue, DOMEventTargetHelper)
     31 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TextTrackCue)
     32 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
     33 
     34 StaticRefPtr<nsIWebVTTParserWrapper> TextTrackCue::sParserWrapper;
     35 
     36 // Set default value for cue, spec https://w3c.github.io/webvtt/#model-cues
     37 void TextTrackCue::SetDefaultCueSettings() {
     38  mPositionIsAutoKeyword = true;
     39  // Spec https://www.w3.org/TR/webvtt1/#webvtt-cue-position-automatic-alignment
     40  mPositionAlign = PositionAlignSetting::Auto;
     41  mSize = 100.0;
     42  mPauseOnExit = false;
     43  mSnapToLines = true;
     44  mLineIsAutoKeyword = true;
     45  mAlign = AlignSetting::Center;
     46  mLineAlign = LineAlignSetting::Start;
     47  mVertical = DirectionSetting::_empty;
     48  mActive = false;
     49 }
     50 
     51 TextTrackCue::TextTrackCue(nsPIDOMWindowInner* aOwnerWindow, double aStartTime,
     52                           double aEndTime, const nsAString& aText,
     53                           ErrorResult& aRv)
     54    : DOMEventTargetHelper(aOwnerWindow),
     55      mText(aText),
     56      mStartTime(aStartTime),
     57      mEndTime(aEndTime),
     58      mPosition(0.0),
     59      mLine(0.0),
     60      mReset(false, "TextTrackCue::mReset"),
     61      mHaveStartedWatcher(false),
     62      mWatchManager(this, AbstractThread::MainThread()) {
     63  LOG("create TextTrackCue");
     64  SetDefaultCueSettings();
     65  MOZ_ASSERT(aOwnerWindow);
     66  if (NS_FAILED(StashDocument())) {
     67    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     68  }
     69 }
     70 
     71 TextTrackCue::TextTrackCue(nsPIDOMWindowInner* aOwnerWindow, double aStartTime,
     72                           double aEndTime, const nsAString& aText,
     73                           HTMLTrackElement* aTrackElement, ErrorResult& aRv)
     74    : DOMEventTargetHelper(aOwnerWindow),
     75      mText(aText),
     76      mStartTime(aStartTime),
     77      mEndTime(aEndTime),
     78      mTrackElement(aTrackElement),
     79      mPosition(0.0),
     80      mLine(0.0),
     81      mReset(false, "TextTrackCue::mReset"),
     82      mHaveStartedWatcher(false),
     83      mWatchManager(this, AbstractThread::MainThread()) {
     84  LOG("create TextTrackCue");
     85  SetDefaultCueSettings();
     86  MOZ_ASSERT(aOwnerWindow);
     87  if (NS_FAILED(StashDocument())) {
     88    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     89  }
     90 }
     91 
     92 TextTrackCue::~TextTrackCue() = default;
     93 
     94 /** Save a reference to our creating document so we don't have to
     95 *  keep getting it from our window.
     96 */
     97 nsresult TextTrackCue::StashDocument() {
     98  nsPIDOMWindowInner* window = GetOwnerWindow();
     99  if (!window) {
    100    return NS_ERROR_NO_INTERFACE;
    101  }
    102  mDocument = window->GetDoc();
    103  if (!mDocument) {
    104    return NS_ERROR_NOT_AVAILABLE;
    105  }
    106  return NS_OK;
    107 }
    108 
    109 already_AddRefed<DocumentFragment> TextTrackCue::GetCueAsHTML() {
    110  // mDocument may be null during cycle collector shutdown.
    111  // See bug 941701.
    112  if (!mDocument) {
    113    return nullptr;
    114  }
    115 
    116  if (!sParserWrapper) {
    117    nsresult rv;
    118    nsCOMPtr<nsIWebVTTParserWrapper> parserWrapper =
    119        do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID, &rv);
    120    if (NS_FAILED(rv)) {
    121      return mDocument->CreateDocumentFragment();
    122    }
    123    sParserWrapper = parserWrapper;
    124    ClearOnShutdown(&sParserWrapper);
    125  }
    126 
    127  nsPIDOMWindowInner* window = mDocument->GetInnerWindow();
    128  if (!window) {
    129    return mDocument->CreateDocumentFragment();
    130  }
    131 
    132  RefPtr<DocumentFragment> frag;
    133  sParserWrapper->ConvertCueToDOMTree(window, static_cast<EventTarget*>(this),
    134                                      getter_AddRefs(frag));
    135  if (!frag) {
    136    return mDocument->CreateDocumentFragment();
    137  }
    138  return frag.forget();
    139 }
    140 
    141 void TextTrackCue::SetTrackElement(HTMLTrackElement* aTrackElement) {
    142  mTrackElement = aTrackElement;
    143 }
    144 
    145 JSObject* TextTrackCue::WrapObject(JSContext* aCx,
    146                                   JS::Handle<JSObject*> aGivenProto) {
    147  return VTTCue_Binding::Wrap(aCx, this, aGivenProto);
    148 }
    149 
    150 TextTrackRegion* TextTrackCue::GetRegion() { return mRegion; }
    151 
    152 void TextTrackCue::SetRegion(TextTrackRegion* aRegion) {
    153  if (mRegion == aRegion) {
    154    return;
    155  }
    156  mRegion = aRegion;
    157  mReset = true;
    158 }
    159 
    160 double TextTrackCue::ComputedLine() {
    161  // See spec https://w3c.github.io/webvtt/#cue-computed-line
    162  if (!mLineIsAutoKeyword && !mSnapToLines && (mLine < 0.0 || mLine > 100.0)) {
    163    return 100.0;
    164  } else if (!mLineIsAutoKeyword) {
    165    return mLine;
    166  } else if (mLineIsAutoKeyword && !mSnapToLines) {
    167    return 100.0;
    168  } else if (!mTrack || !mTrack->GetTextTrackList() ||
    169             !mTrack->GetTextTrackList()->GetMediaElement()) {
    170    return -1.0;
    171  }
    172 
    173  RefPtr<TextTrackList> trackList = mTrack->GetTextTrackList();
    174  bool dummy;
    175  uint32_t showingTracksNum = 0;
    176  for (uint32_t idx = 0; idx < trackList->Length(); idx++) {
    177    RefPtr<TextTrack> track = trackList->IndexedGetter(idx, dummy);
    178    if (track->Mode() == TextTrackMode::Showing) {
    179      showingTracksNum++;
    180    }
    181 
    182    if (mTrack == track) {
    183      break;
    184    }
    185  }
    186 
    187  return (-1.0) * showingTracksNum;
    188 }
    189 
    190 double TextTrackCue::ComputedPosition() {
    191  // See spec https://w3c.github.io/webvtt/#cue-computed-position
    192  if (!mPositionIsAutoKeyword) {
    193    return mPosition;
    194  }
    195  if (ComputedPositionAlign() == PositionAlignSetting::Line_left) {
    196    return 0.0;
    197  }
    198  if (ComputedPositionAlign() == PositionAlignSetting::Line_right) {
    199    return 100.0;
    200  }
    201  return 50.0;
    202 }
    203 
    204 PositionAlignSetting TextTrackCue::ComputedPositionAlign() {
    205  // See spec https://w3c.github.io/webvtt/#cue-computed-position-alignment
    206  if (mPositionAlign != PositionAlignSetting::Auto) {
    207    return mPositionAlign;
    208  } else if (mAlign == AlignSetting::Left) {
    209    return PositionAlignSetting::Line_left;
    210  } else if (mAlign == AlignSetting::Right) {
    211    return PositionAlignSetting::Line_right;
    212  } else if (mAlign == AlignSetting::Start) {
    213    return IsTextBaseDirectionLTR() ? PositionAlignSetting::Line_left
    214                                    : PositionAlignSetting::Line_right;
    215  } else if (mAlign == AlignSetting::End) {
    216    return IsTextBaseDirectionLTR() ? PositionAlignSetting::Line_right
    217                                    : PositionAlignSetting::Line_left;
    218  }
    219  return PositionAlignSetting::Center;
    220 }
    221 
    222 bool TextTrackCue::IsTextBaseDirectionLTR() const {
    223  // The result returned by `GetBaseDirection` might be `neutral` if the text
    224  // only contains neutral charaters. In this case, we would treat its base
    225  // direction as LTR.
    226  return intl::Bidi::GetBaseDirection(mText) != intl::Bidi::BaseDirection::RTL;
    227 }
    228 
    229 void TextTrackCue::NotifyDisplayStatesChanged() {
    230  if (!mReset) {
    231    return;
    232  }
    233 
    234  if (!mTrack || !mTrack->GetTextTrackList() ||
    235      !mTrack->GetTextTrackList()->GetMediaElement()) {
    236    return;
    237  }
    238 
    239  mTrack->GetTextTrackList()
    240      ->GetMediaElement()
    241      ->NotifyCueDisplayStatesChanged();
    242 }
    243 
    244 void TextTrackCue::SetActive(bool aActive) {
    245  if (mActive == aActive) {
    246    return;
    247  }
    248 
    249  LOG("TextTrackCue, SetActive=%d", aActive);
    250  mActive = aActive;
    251  mDisplayState = mActive ? mDisplayState : nullptr;
    252  if (mTrack) {
    253    mTrack->NotifyCueActiveStateChanged(this);
    254  }
    255 }
    256 
    257 #undef LOG
    258 
    259 }  // namespace mozilla::dom