Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim:set ts=2 sw=2 et tw=78: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef mozilla_dom_TextTrackCue_h
8 : #define mozilla_dom_TextTrackCue_h
9 :
10 : #include "mozilla/DOMEventTargetHelper.h"
11 : #include "mozilla/dom/DocumentFragment.h"
12 : #include "mozilla/dom/VTTCueBinding.h"
13 : #include "nsCycleCollectionParticipant.h"
14 : #include "nsIWebVTTParserWrapper.h"
15 : #include "mozilla/StaticPtr.h"
16 : #include "nsIDocument.h"
17 : #include "mozilla/dom/HTMLDivElement.h"
18 : #include "mozilla/dom/TextTrack.h"
19 : #include "mozilla/StateWatching.h"
20 :
21 : namespace mozilla {
22 : namespace dom {
23 :
24 : class HTMLTrackElement;
25 : class TextTrackRegion;
26 :
27 : class TextTrackCue final : public DOMEventTargetHelper
28 : {
29 : public:
30 : NS_DECL_ISUPPORTS_INHERITED
31 0 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TextTrackCue, DOMEventTargetHelper)
32 :
33 : // TextTrackCue WebIDL
34 : // See bug 868509 about splitting out the WebVTT-specific interfaces.
35 : static already_AddRefed<TextTrackCue>
36 0 : Constructor(GlobalObject& aGlobal,
37 : double aStartTime,
38 : double aEndTime,
39 : const nsAString& aText,
40 : ErrorResult& aRv)
41 : {
42 0 : nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
43 : RefPtr<TextTrackCue> ttcue = new TextTrackCue(window, aStartTime,
44 0 : aEndTime, aText, aRv);
45 0 : return ttcue.forget();
46 : }
47 : TextTrackCue(nsPIDOMWindowInner* aGlobal, double aStartTime, double aEndTime,
48 : const nsAString& aText, ErrorResult& aRv);
49 :
50 : TextTrackCue(nsPIDOMWindowInner* aGlobal, double aStartTime, double aEndTime,
51 : const nsAString& aText, HTMLTrackElement* aTrackElement,
52 : ErrorResult& aRv);
53 :
54 : JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
55 :
56 0 : TextTrack* GetTrack() const
57 : {
58 0 : return mTrack;
59 : }
60 :
61 0 : void GetId(nsAString& aId) const
62 : {
63 0 : aId = mId;
64 0 : }
65 :
66 0 : void SetId(const nsAString& aId)
67 : {
68 0 : if (mId == aId) {
69 0 : return;
70 : }
71 :
72 0 : mId = aId;
73 : }
74 :
75 0 : double StartTime() const
76 : {
77 0 : return mStartTime;
78 : }
79 :
80 0 : void SetStartTime(double aStartTime)
81 : {
82 0 : if (mStartTime == aStartTime) {
83 0 : return;
84 : }
85 :
86 0 : mStartTime = aStartTime;
87 0 : mReset = true;
88 0 : NotifyCueUpdated(this);
89 : }
90 :
91 0 : double EndTime() const
92 : {
93 0 : return mEndTime;
94 : }
95 :
96 0 : void SetEndTime(double aEndTime)
97 : {
98 0 : if (mEndTime == aEndTime) {
99 0 : return;
100 : }
101 :
102 0 : mEndTime = aEndTime;
103 0 : mReset = true;
104 0 : NotifyCueUpdated(this);
105 : }
106 :
107 0 : bool PauseOnExit()
108 : {
109 0 : return mPauseOnExit;
110 : }
111 :
112 0 : void SetPauseOnExit(bool aPauseOnExit)
113 : {
114 0 : if (mPauseOnExit == aPauseOnExit) {
115 0 : return;
116 : }
117 :
118 0 : mPauseOnExit = aPauseOnExit;
119 0 : NotifyCueUpdated(nullptr);
120 : }
121 :
122 : TextTrackRegion* GetRegion();
123 : void SetRegion(TextTrackRegion* aRegion);
124 :
125 0 : DirectionSetting Vertical() const
126 : {
127 0 : return mVertical;
128 : }
129 :
130 0 : void SetVertical(const DirectionSetting& aVertical)
131 : {
132 0 : if (mVertical == aVertical) {
133 0 : return;
134 : }
135 :
136 0 : mReset = true;
137 0 : mVertical = aVertical;
138 : }
139 :
140 0 : bool SnapToLines()
141 : {
142 0 : return mSnapToLines;
143 : }
144 :
145 0 : void SetSnapToLines(bool aSnapToLines)
146 : {
147 0 : if (mSnapToLines == aSnapToLines) {
148 0 : return;
149 : }
150 :
151 0 : mReset = true;
152 0 : mSnapToLines = aSnapToLines;
153 : }
154 :
155 0 : void GetLine(OwningDoubleOrAutoKeyword& aLine) const
156 : {
157 0 : if (mLineIsAutoKeyword) {
158 0 : aLine.SetAsAutoKeyword() = AutoKeyword::Auto;
159 0 : return;
160 : }
161 0 : aLine.SetAsDouble() = mLine;
162 : }
163 :
164 0 : void SetLine(const DoubleOrAutoKeyword& aLine)
165 : {
166 0 : if (aLine.IsDouble() &&
167 0 : (mLineIsAutoKeyword || (aLine.GetAsDouble() != mLine))) {
168 0 : mLineIsAutoKeyword = false;
169 0 : mLine = aLine.GetAsDouble();
170 0 : mReset = true;
171 0 : return;
172 : }
173 0 : if (aLine.IsAutoKeyword() && !mLineIsAutoKeyword) {
174 0 : mLineIsAutoKeyword = true;
175 0 : mReset = true;
176 : }
177 : }
178 :
179 0 : LineAlignSetting LineAlign() const
180 : {
181 0 : return mLineAlign;
182 : }
183 :
184 0 : void SetLineAlign(LineAlignSetting& aLineAlign, ErrorResult& aRv)
185 : {
186 0 : if (mLineAlign == aLineAlign) {
187 0 : return;
188 : }
189 :
190 0 : mReset = true;
191 0 : mLineAlign = aLineAlign;
192 : }
193 :
194 0 : void GetPosition(OwningDoubleOrAutoKeyword& aPosition) const
195 : {
196 0 : if (mPositionIsAutoKeyword) {
197 0 : aPosition.SetAsAutoKeyword() = AutoKeyword::Auto;
198 0 : return;
199 : }
200 0 : aPosition.SetAsDouble() = mPosition;
201 : }
202 :
203 0 : void SetPosition(const DoubleOrAutoKeyword& aPosition, ErrorResult& aRv)
204 : {
205 0 : if (!aPosition.IsAutoKeyword() &&
206 0 : (aPosition.GetAsDouble() > 100.0 || aPosition.GetAsDouble() < 0.0)){
207 0 : aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
208 0 : return;
209 : }
210 :
211 0 : if (aPosition.IsDouble() &&
212 0 : (mPositionIsAutoKeyword || (aPosition.GetAsDouble() != mPosition))) {
213 0 : mPositionIsAutoKeyword = false;
214 0 : mPosition = aPosition.GetAsDouble();
215 0 : mReset = true;
216 0 : return;
217 : }
218 :
219 0 : if (aPosition.IsAutoKeyword() && !mPositionIsAutoKeyword) {
220 0 : mPositionIsAutoKeyword = true;
221 0 : mReset = true;
222 : }
223 : }
224 :
225 0 : PositionAlignSetting PositionAlign() const
226 : {
227 0 : return mPositionAlign;
228 : }
229 :
230 0 : void SetPositionAlign(PositionAlignSetting aPositionAlign, ErrorResult& aRv)
231 : {
232 0 : if (mPositionAlign == aPositionAlign) {
233 0 : return;
234 : }
235 :
236 0 : mReset = true;
237 0 : mPositionAlign = aPositionAlign;
238 : }
239 :
240 0 : double Size() const
241 : {
242 0 : return mSize;
243 : }
244 :
245 0 : void SetSize(double aSize, ErrorResult& aRv)
246 : {
247 0 : if (mSize == aSize) {
248 0 : return;
249 : }
250 :
251 0 : if (aSize < 0.0 || aSize > 100.0) {
252 0 : aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
253 0 : return;
254 : }
255 :
256 0 : mReset = true;
257 0 : mSize = aSize;
258 : }
259 :
260 0 : AlignSetting Align() const
261 : {
262 0 : return mAlign;
263 : }
264 :
265 0 : void SetAlign(AlignSetting& aAlign)
266 : {
267 0 : if (mAlign == aAlign) {
268 0 : return;
269 : }
270 :
271 0 : mReset = true;
272 0 : mAlign = aAlign;
273 : }
274 :
275 0 : void GetText(nsAString& aText) const
276 : {
277 0 : aText = mText;
278 0 : }
279 :
280 0 : void SetText(const nsAString& aText)
281 : {
282 0 : if (mText == aText) {
283 0 : return;
284 : }
285 :
286 0 : mReset = true;
287 0 : mText = aText;
288 : }
289 :
290 0 : IMPL_EVENT_HANDLER(enter)
291 0 : IMPL_EVENT_HANDLER(exit)
292 :
293 0 : HTMLDivElement* GetDisplayState()
294 : {
295 0 : return static_cast<HTMLDivElement*>(mDisplayState.get());
296 : }
297 :
298 0 : void SetDisplayState(HTMLDivElement* aDisplayState)
299 : {
300 0 : mDisplayState = aDisplayState;
301 0 : mReset = false;
302 0 : }
303 :
304 0 : void Reset()
305 : {
306 0 : mReset = true;
307 0 : }
308 :
309 0 : bool HasBeenReset()
310 : {
311 0 : return mReset;
312 : }
313 :
314 : double ComputedLine();
315 : double ComputedPosition();
316 : PositionAlignSetting ComputedPositionAlign();
317 :
318 : // Helper functions for implementation.
319 0 : const nsAString& Id() const
320 : {
321 0 : return mId;
322 : }
323 :
324 0 : void SetTrack(TextTrack* aTextTrack)
325 : {
326 0 : mTrack = aTextTrack;
327 0 : if (!mHaveStartedWatcher && aTextTrack) {
328 0 : mHaveStartedWatcher = true;
329 0 : mWatchManager.Watch(mReset, &TextTrackCue::NotifyDisplayStatesChanged);
330 0 : } else if (mHaveStartedWatcher && !aTextTrack) {
331 0 : mHaveStartedWatcher = false;
332 0 : mWatchManager.Unwatch(mReset, &TextTrackCue::NotifyDisplayStatesChanged);
333 : }
334 0 : }
335 :
336 : /**
337 : * Produces a tree of anonymous content based on the tree of the processed
338 : * cue text.
339 : *
340 : * Returns a DocumentFragment that is the head of the tree of anonymous
341 : * content.
342 : */
343 : already_AddRefed<DocumentFragment> GetCueAsHTML();
344 :
345 : void SetTrackElement(HTMLTrackElement* aTrackElement);
346 :
347 0 : void SetActive(bool aActive)
348 : {
349 0 : if (mActive == aActive) {
350 0 : return;
351 : }
352 :
353 0 : mActive = aActive;
354 0 : mDisplayState = mActive ? mDisplayState : nullptr;
355 : }
356 :
357 0 : bool GetActive()
358 : {
359 0 : return mActive;
360 : }
361 :
362 : private:
363 : ~TextTrackCue();
364 :
365 0 : void NotifyCueUpdated(TextTrackCue* aCue)
366 : {
367 0 : if (mTrack) {
368 0 : mTrack->NotifyCueUpdated(aCue);
369 : }
370 0 : }
371 :
372 : void NotifyDisplayStatesChanged();
373 :
374 : void SetDefaultCueSettings();
375 : nsresult StashDocument();
376 :
377 : RefPtr<nsIDocument> mDocument;
378 : nsString mText;
379 : double mStartTime;
380 : double mEndTime;
381 :
382 : RefPtr<TextTrack> mTrack;
383 : RefPtr<HTMLTrackElement> mTrackElement;
384 : nsString mId;
385 : MOZ_INIT_OUTSIDE_CTOR double mPosition;
386 : bool mPositionIsAutoKeyword;
387 : PositionAlignSetting mPositionAlign;
388 : double mSize;
389 : bool mPauseOnExit;
390 : bool mSnapToLines;
391 : RefPtr<TextTrackRegion> mRegion;
392 : DirectionSetting mVertical;
393 : bool mLineIsAutoKeyword;
394 : MOZ_INIT_OUTSIDE_CTOR double mLine;
395 : AlignSetting mAlign;
396 : LineAlignSetting mLineAlign;
397 :
398 : // Holds the computed DOM elements that represent the parsed cue text.
399 : // http://www.whatwg.org/specs/web-apps/current-work/#text-track-cue-display-state
400 : RefPtr<nsGenericHTMLElement> mDisplayState;
401 : // Tells whether or not we need to recompute mDisplayState. This is set
402 : // anytime a property that relates to the display of the TextTrackCue is
403 : // changed.
404 : Watchable<bool> mReset;
405 :
406 : bool mActive;
407 :
408 : static StaticRefPtr<nsIWebVTTParserWrapper> sParserWrapper;
409 :
410 : // Only start watcher after the cue has text track.
411 : bool mHaveStartedWatcher;
412 : WatchManager<TextTrackCue> mWatchManager;
413 : };
414 :
415 : } // namespace dom
416 : } // namespace mozilla
417 :
418 : #endif // mozilla_dom_TextTrackCue_h
|