Line data Source code
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/TextTrackList.h"
7 :
8 : #include "mozilla/DebugOnly.h"
9 : #include "mozilla/dom/TextTrackListBinding.h"
10 : #include "mozilla/dom/TrackEvent.h"
11 : #include "nsThreadUtils.h"
12 : #include "nsGlobalWindow.h"
13 : #include "mozilla/dom/TextTrackCue.h"
14 : #include "mozilla/dom/TextTrackManager.h"
15 :
16 : namespace mozilla {
17 : namespace dom {
18 :
19 0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(TextTrackList,
20 : DOMEventTargetHelper,
21 : mTextTracks,
22 : mTextTrackManager)
23 :
24 0 : NS_IMPL_ADDREF_INHERITED(TextTrackList, DOMEventTargetHelper)
25 0 : NS_IMPL_RELEASE_INHERITED(TextTrackList, DOMEventTargetHelper)
26 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TextTrackList)
27 0 : NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
28 :
29 0 : TextTrackList::TextTrackList(nsPIDOMWindowInner* aOwnerWindow)
30 0 : : DOMEventTargetHelper(aOwnerWindow)
31 : {
32 0 : }
33 :
34 0 : TextTrackList::TextTrackList(nsPIDOMWindowInner* aOwnerWindow,
35 0 : TextTrackManager* aTextTrackManager)
36 : : DOMEventTargetHelper(aOwnerWindow)
37 0 : , mTextTrackManager(aTextTrackManager)
38 : {
39 0 : }
40 :
41 0 : TextTrackList::~TextTrackList()
42 : {
43 0 : }
44 :
45 : void
46 0 : TextTrackList::GetShowingCues(nsTArray<RefPtr<TextTrackCue> >& aCues)
47 : {
48 : // Only Subtitles and Captions can show on the screen.
49 0 : nsTArray< RefPtr<TextTrackCue> > cues;
50 0 : for (uint32_t i = 0; i < Length(); i++) {
51 0 : if (mTextTracks[i]->Mode() == TextTrackMode::Showing &&
52 0 : (mTextTracks[i]->Kind() == TextTrackKind::Subtitles ||
53 0 : mTextTracks[i]->Kind() == TextTrackKind::Captions)) {
54 0 : mTextTracks[i]->GetActiveCueArray(cues);
55 0 : aCues.AppendElements(cues);
56 : }
57 : }
58 0 : }
59 :
60 : JSObject*
61 0 : TextTrackList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
62 : {
63 0 : return TextTrackListBinding::Wrap(aCx, this, aGivenProto);
64 : }
65 :
66 : TextTrack*
67 0 : TextTrackList::IndexedGetter(uint32_t aIndex, bool& aFound)
68 : {
69 0 : aFound = aIndex < mTextTracks.Length();
70 0 : if (!aFound) {
71 0 : return nullptr;
72 : }
73 0 : return mTextTracks[aIndex];
74 : }
75 :
76 : TextTrack*
77 0 : TextTrackList::operator[](uint32_t aIndex)
78 : {
79 0 : return mTextTracks.SafeElementAt(aIndex, nullptr);
80 : }
81 :
82 : already_AddRefed<TextTrack>
83 0 : TextTrackList::AddTextTrack(TextTrackKind aKind,
84 : const nsAString& aLabel,
85 : const nsAString& aLanguage,
86 : TextTrackMode aMode,
87 : TextTrackReadyState aReadyState,
88 : TextTrackSource aTextTrackSource,
89 : const CompareTextTracks& aCompareTT)
90 : {
91 0 : RefPtr<TextTrack> track = new TextTrack(GetOwner(), this, aKind, aLabel,
92 : aLanguage, aMode, aReadyState,
93 0 : aTextTrackSource);
94 0 : AddTextTrack(track, aCompareTT);
95 0 : return track.forget();
96 : }
97 :
98 : void
99 0 : TextTrackList::AddTextTrack(TextTrack* aTextTrack,
100 : const CompareTextTracks& aCompareTT)
101 : {
102 0 : if (mTextTracks.Contains(aTextTrack)) {
103 0 : return;
104 : }
105 0 : if (mTextTracks.InsertElementSorted(aTextTrack, aCompareTT)) {
106 0 : aTextTrack->SetTextTrackList(this);
107 0 : CreateAndDispatchTrackEventRunner(aTextTrack, NS_LITERAL_STRING("addtrack"));
108 : }
109 : }
110 :
111 : TextTrack*
112 0 : TextTrackList::GetTrackById(const nsAString& aId)
113 : {
114 0 : nsAutoString id;
115 0 : for (uint32_t i = 0; i < Length(); i++) {
116 0 : mTextTracks[i]->GetId(id);
117 0 : if (aId.Equals(id)) {
118 0 : return mTextTracks[i];
119 : }
120 : }
121 0 : return nullptr;
122 : }
123 :
124 : void
125 0 : TextTrackList::RemoveTextTrack(TextTrack* aTrack)
126 : {
127 0 : if (mTextTracks.RemoveElement(aTrack)) {
128 0 : CreateAndDispatchTrackEventRunner(aTrack, NS_LITERAL_STRING("removetrack"));
129 : }
130 0 : }
131 :
132 : void
133 0 : TextTrackList::DidSeek()
134 : {
135 0 : for (uint32_t i = 0; i < mTextTracks.Length(); i++) {
136 0 : mTextTracks[i]->SetDirty();
137 : }
138 0 : }
139 :
140 0 : class TrackEventRunner : public Runnable
141 : {
142 : public:
143 0 : TrackEventRunner(TextTrackList* aList, nsIDOMEvent* aEvent)
144 0 : : Runnable("dom::TrackEventRunner")
145 : , mList(aList)
146 0 : , mEvent(aEvent)
147 0 : {}
148 :
149 0 : NS_IMETHOD Run() override
150 : {
151 0 : return mList->DispatchTrackEvent(mEvent);
152 : }
153 :
154 : RefPtr<TextTrackList> mList;
155 : private:
156 : RefPtr<nsIDOMEvent> mEvent;
157 : };
158 :
159 0 : class ChangeEventRunner final : public TrackEventRunner
160 : {
161 : public:
162 0 : ChangeEventRunner(TextTrackList* aList, nsIDOMEvent* aEvent)
163 0 : : TrackEventRunner(aList, aEvent)
164 0 : {}
165 :
166 0 : NS_IMETHOD Run() override
167 : {
168 0 : mList->mPendingTextTrackChange = false;
169 0 : return TrackEventRunner::Run();
170 : }
171 : };
172 :
173 : nsresult
174 0 : TextTrackList::DispatchTrackEvent(nsIDOMEvent* aEvent)
175 : {
176 0 : return DispatchTrustedEvent(aEvent);
177 : }
178 :
179 : void
180 0 : TextTrackList::CreateAndDispatchChangeEvent()
181 : {
182 0 : MOZ_ASSERT(NS_IsMainThread());
183 0 : if (!mPendingTextTrackChange) {
184 0 : nsPIDOMWindowInner* win = GetOwner();
185 0 : if (!win) {
186 0 : return;
187 : }
188 :
189 0 : mPendingTextTrackChange = true;
190 0 : RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
191 :
192 0 : event->InitEvent(NS_LITERAL_STRING("change"), false, false);
193 0 : event->SetTrusted(true);
194 :
195 0 : nsCOMPtr<nsIRunnable> eventRunner = new ChangeEventRunner(this, event);
196 0 : nsGlobalWindow::Cast(win)->Dispatch(
197 : "TextTrackList::CreateAndDispatchChangeEvent", TaskCategory::Other,
198 0 : eventRunner.forget());
199 : }
200 : }
201 :
202 : void
203 0 : TextTrackList::CreateAndDispatchTrackEventRunner(TextTrack* aTrack,
204 : const nsAString& aEventName)
205 : {
206 0 : DebugOnly<nsresult> rv;
207 0 : nsCOMPtr<nsIEventTarget> target = GetMainThreadEventTarget();
208 0 : if (!target) {
209 : // If we are not able to get the main-thread object we are shutting down.
210 0 : return;
211 : }
212 :
213 0 : TrackEventInit eventInit;
214 0 : eventInit.mTrack.SetValue().SetAsTextTrack() = aTrack;
215 : RefPtr<TrackEvent> event =
216 0 : TrackEvent::Constructor(this, aEventName, eventInit);
217 :
218 : // Dispatch the TrackEvent asynchronously.
219 0 : rv = target->Dispatch(do_AddRef(new TrackEventRunner(this, event)),
220 0 : NS_DISPATCH_NORMAL);
221 :
222 : // If we are shutting down this can file but it's still ok.
223 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Dispatch failed");
224 : }
225 :
226 : HTMLMediaElement*
227 0 : TextTrackList::GetMediaElement()
228 : {
229 0 : if (mTextTrackManager) {
230 0 : return mTextTrackManager->mMediaElement;
231 : }
232 0 : return nullptr;
233 : }
234 :
235 : void
236 0 : TextTrackList::SetTextTrackManager(TextTrackManager* aTextTrackManager)
237 : {
238 0 : mTextTrackManager = aTextTrackManager;
239 0 : }
240 :
241 : void
242 0 : TextTrackList::SetCuesInactive()
243 : {
244 0 : for (uint32_t i = 0; i < Length(); i++) {
245 0 : mTextTracks[i]->SetCuesInactive();
246 : }
247 0 : }
248 :
249 :
250 0 : bool TextTrackList::AreTextTracksLoaded()
251 : {
252 : // Return false if any texttrack is not loaded.
253 0 : for (uint32_t i = 0; i < Length(); i++) {
254 0 : if (!mTextTracks[i]->IsLoaded()) {
255 0 : return false;
256 : }
257 : }
258 0 : return true;
259 : }
260 :
261 : nsTArray<RefPtr<TextTrack>>&
262 0 : TextTrackList::GetTextTrackArray()
263 : {
264 0 : return mTextTracks;
265 : }
266 :
267 : } // namespace dom
268 : } // namespace mozilla
|