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