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/. */
6 #include "mozilla/dom/TextTrackList.h"
8 #include "mozilla/DebugOnly.h"
9 #include "mozilla/dom/Event.h"
10 #include "mozilla/dom/TextTrackListBinding.h"
11 #include "mozilla/dom/TrackEvent.h"
12 #include "nsThreadUtils.h"
13 #include "nsGlobalWindowInner.h"
14 #include "mozilla/dom/TextTrackCue.h"
15 #include "mozilla/dom/TextTrackManager.h"
17 namespace mozilla::dom
{
19 NS_IMPL_CYCLE_COLLECTION_INHERITED(TextTrackList
, DOMEventTargetHelper
,
20 mTextTracks
, mTextTrackManager
)
22 NS_IMPL_ADDREF_INHERITED(TextTrackList
, DOMEventTargetHelper
)
23 NS_IMPL_RELEASE_INHERITED(TextTrackList
, DOMEventTargetHelper
)
24 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TextTrackList
)
25 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
27 TextTrackList::TextTrackList(nsPIDOMWindowInner
* aOwnerWindow
)
28 : DOMEventTargetHelper(aOwnerWindow
) {}
30 TextTrackList::TextTrackList(nsPIDOMWindowInner
* aOwnerWindow
,
31 TextTrackManager
* aTextTrackManager
)
32 : DOMEventTargetHelper(aOwnerWindow
),
33 mTextTrackManager(aTextTrackManager
) {}
35 TextTrackList::~TextTrackList() = default;
37 void TextTrackList::GetShowingCues(nsTArray
<RefPtr
<TextTrackCue
>>& aCues
) {
38 // Only Subtitles and Captions can show on the screen.
39 nsTArray
<RefPtr
<TextTrackCue
>> cues
;
40 for (uint32_t i
= 0; i
< Length(); i
++) {
41 if (mTextTracks
[i
]->Mode() == TextTrackMode::Showing
&&
42 (mTextTracks
[i
]->Kind() == TextTrackKind::Subtitles
||
43 mTextTracks
[i
]->Kind() == TextTrackKind::Captions
)) {
44 mTextTracks
[i
]->GetActiveCueArray(cues
);
45 aCues
.AppendElements(cues
);
50 JSObject
* TextTrackList::WrapObject(JSContext
* aCx
,
51 JS::Handle
<JSObject
*> aGivenProto
) {
52 return TextTrackList_Binding::Wrap(aCx
, this, aGivenProto
);
55 TextTrack
* TextTrackList::IndexedGetter(uint32_t aIndex
, bool& aFound
) {
56 aFound
= aIndex
< mTextTracks
.Length();
60 return mTextTracks
[aIndex
];
63 TextTrack
* TextTrackList::operator[](uint32_t aIndex
) {
64 return mTextTracks
.SafeElementAt(aIndex
, nullptr);
67 already_AddRefed
<TextTrack
> TextTrackList::AddTextTrack(
68 TextTrackKind aKind
, const nsAString
& aLabel
, const nsAString
& aLanguage
,
69 TextTrackMode aMode
, TextTrackReadyState aReadyState
,
70 TextTrackSource aTextTrackSource
, const CompareTextTracks
& aCompareTT
) {
71 RefPtr
<TextTrack
> track
=
72 new TextTrack(GetOwnerWindow(), this, aKind
, aLabel
, aLanguage
, aMode
,
73 aReadyState
, aTextTrackSource
);
74 AddTextTrack(track
, aCompareTT
);
75 return track
.forget();
78 void TextTrackList::AddTextTrack(TextTrack
* aTextTrack
,
79 const CompareTextTracks
& aCompareTT
) {
80 if (mTextTracks
.Contains(aTextTrack
)) {
83 mTextTracks
.InsertElementSorted(aTextTrack
, aCompareTT
);
84 aTextTrack
->SetTextTrackList(this);
85 CreateAndDispatchTrackEventRunner(aTextTrack
, u
"addtrack"_ns
);
88 TextTrack
* TextTrackList::GetTrackById(const nsAString
& aId
) {
90 for (uint32_t i
= 0; i
< Length(); i
++) {
91 mTextTracks
[i
]->GetId(id
);
93 return mTextTracks
[i
];
99 void TextTrackList::RemoveTextTrack(TextTrack
* aTrack
) {
100 if (mTextTracks
.RemoveElement(aTrack
)) {
101 CreateAndDispatchTrackEventRunner(aTrack
, u
"removetrack"_ns
);
105 class TrackEventRunner
: public Runnable
{
107 TrackEventRunner(TextTrackList
* aList
, Event
* aEvent
)
108 : Runnable("dom::TrackEventRunner"), mList(aList
), mEvent(aEvent
) {}
110 NS_IMETHOD
Run() override
{ return mList
->DispatchTrackEvent(mEvent
); }
112 RefPtr
<TextTrackList
> mList
;
115 RefPtr
<Event
> mEvent
;
118 nsresult
TextTrackList::DispatchTrackEvent(Event
* aEvent
) {
119 return DispatchTrustedEvent(aEvent
);
122 void TextTrackList::CreateAndDispatchChangeEvent() {
123 MOZ_ASSERT(NS_IsMainThread());
124 nsPIDOMWindowInner
* win
= GetOwnerWindow();
129 RefPtr
<Event
> event
= NS_NewDOMEvent(this, nullptr, nullptr);
131 event
->InitEvent(u
"change"_ns
, false, false);
132 event
->SetTrusted(true);
134 nsCOMPtr
<nsIRunnable
> eventRunner
= new TrackEventRunner(this, event
);
135 nsGlobalWindowInner::Cast(win
)->Dispatch(eventRunner
.forget());
138 void TextTrackList::CreateAndDispatchTrackEventRunner(
139 TextTrack
* aTrack
, const nsAString
& aEventName
) {
140 nsCOMPtr
<nsIEventTarget
> target
= GetMainThreadSerialEventTarget();
142 // If we are not able to get the main-thread object we are shutting down.
146 TrackEventInit eventInit
;
147 eventInit
.mTrack
.SetValue().SetAsTextTrack() = aTrack
;
148 RefPtr
<TrackEvent
> event
=
149 TrackEvent::Constructor(this, aEventName
, eventInit
);
151 // Dispatch the TrackEvent asynchronously.
152 DebugOnly
<nsresult
> rv
= target
->Dispatch(
153 do_AddRef(new TrackEventRunner(this, event
)), NS_DISPATCH_NORMAL
);
155 // If we are shutting down this can file but it's still ok.
156 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
), "Dispatch failed");
159 HTMLMediaElement
* TextTrackList::GetMediaElement() {
160 if (mTextTrackManager
) {
161 return mTextTrackManager
->mMediaElement
;
166 void TextTrackList::SetTextTrackManager(TextTrackManager
* aTextTrackManager
) {
167 mTextTrackManager
= aTextTrackManager
;
170 void TextTrackList::SetCuesInactive() {
171 for (uint32_t i
= 0; i
< Length(); i
++) {
172 mTextTracks
[i
]->SetCuesInactive();
176 bool TextTrackList::AreTextTracksLoaded() {
177 // Return false if any texttrack is not loaded.
178 for (uint32_t i
= 0; i
< Length(); i
++) {
179 if (!mTextTracks
[i
]->IsLoaded()) {
186 nsTArray
<RefPtr
<TextTrack
>>& TextTrackList::GetTextTrackArray() {
190 } // namespace mozilla::dom