1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_dom_TextTrackManager_h
8 #define mozilla_dom_TextTrackManager_h
9 
10 #include "mozilla/dom/TextTrack.h"
11 #include "mozilla/dom/TextTrackList.h"
12 #include "mozilla/dom/TextTrackCueList.h"
13 #include "mozilla/StaticPtr.h"
14 #include "nsContentUtils.h"
15 #include "nsIDOMEventListener.h"
16 #include "TimeUnits.h"
17 
18 class nsIWebVTTParserWrapper;
19 
20 namespace mozilla {
21 namespace dom {
22 
23 class HTMLMediaElement;
24 
25 class CompareTextTracks {
26  private:
27   HTMLMediaElement* mMediaElement;
28   int32_t TrackChildPosition(TextTrack* aTrack) const;
29 
30  public:
31   explicit CompareTextTracks(HTMLMediaElement* aMediaElement);
32   bool Equals(TextTrack* aOne, TextTrack* aTwo) const;
33   bool LessThan(TextTrack* aOne, TextTrack* aTwo) const;
34 };
35 
36 class TextTrack;
37 class TextTrackCue;
38 
39 class TextTrackManager final : public nsIDOMEventListener {
40   ~TextTrackManager();
41 
42  public:
43   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
44   NS_DECL_CYCLE_COLLECTION_CLASS(TextTrackManager)
45 
46   NS_DECL_NSIDOMEVENTLISTENER
47 
48   explicit TextTrackManager(HTMLMediaElement* aMediaElement);
49 
50   TextTrackList* GetTextTracks() const;
51   already_AddRefed<TextTrack> AddTextTrack(TextTrackKind aKind,
52                                            const nsAString& aLabel,
53                                            const nsAString& aLanguage,
54                                            TextTrackMode aMode,
55                                            TextTrackReadyState aReadyState,
56                                            TextTrackSource aTextTrackSource);
57   void AddTextTrack(TextTrack* aTextTrack);
58   void RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly);
59   void DidSeek();
60 
61   void NotifyCueAdded(TextTrackCue& aCue);
62   void AddCues(TextTrack* aTextTrack);
63   void NotifyCueRemoved(TextTrackCue& aCue);
64   /**
65    * Overview of WebVTT cuetext and anonymous content setup.
66    *
67    * WebVTT nodes are the parsed version of WebVTT cuetext. WebVTT cuetext is
68    * the portion of a WebVTT cue that specifies what the caption will actually
69    * show up as on screen.
70    *
71    * WebVTT cuetext can contain markup that loosely relates to HTML markup. It
72    * can contain tags like <b>, <u>, <i>, <c>, <v>, <ruby>, <rt>, <lang>,
73    * including timestamp tags.
74    *
75    * When the caption is ready to be displayed the WebVTT nodes are converted
76    * over to anonymous DOM content. <i>, <u>, <b>, <ruby>, and <rt> all become
77    * HTMLElements of their corresponding HTML markup tags. <c> and <v> are
78    * converted to <span> tags. Timestamp tags are converted to XML processing
79    * instructions. Additionally, all cuetext tags support specifying of classes.
80    * This takes the form of <foo.class.subclass>. These classes are then parsed
81    * and set as the anonymous content's class attribute.
82    *
83    * Rules on constructing DOM objects from WebVTT nodes can be found here
84    * http://dev.w3.org/html5/webvtt/#webvtt-cue-text-dom-construction-rules.
85    * Current rules are taken from revision on April 15, 2013.
86    */
87 
88   void PopulatePendingList();
89 
90   void AddListeners();
91 
92   // The HTMLMediaElement that this TextTrackManager manages the TextTracks of.
93   RefPtr<HTMLMediaElement> mMediaElement;
94 
95   void DispatchTimeMarchesOn();
96   void TimeMarchesOn();
97   void DispatchUpdateCueDisplay();
98 
NotifyShutdown()99   void NotifyShutdown() { mShutdown = true; }
100 
101   void NotifyCueUpdated(TextTrackCue* aCue);
102 
103   void NotifyReset();
104 
105   bool IsLoaded();
106 
107  private:
108   /**
109    * Converts the TextTrackCue's cuetext into a tree of DOM objects
110    * and attaches it to a div on its owning TrackElement's
111    * MediaElement's caption overlay.
112    */
113   void UpdateCueDisplay();
114 
115   // List of the TextTrackManager's owning HTMLMediaElement's TextTracks.
116   RefPtr<TextTrackList> mTextTracks;
117   // List of text track objects awaiting loading.
118   RefPtr<TextTrackList> mPendingTextTracks;
119   // List of newly introduced Text Track cues.
120 
121   // Contain all cues for a MediaElement. Not sorted.
122   RefPtr<TextTrackCueList> mNewCues;
123 
124   // True if the media player playback changed due to seeking prior to and
125   // during running the "Time Marches On" algorithm.
126   bool mHasSeeked;
127   // Playback position at the time of last "Time Marches On" call
128   media::TimeUnit mLastTimeMarchesOnCalled;
129 
130   bool mTimeMarchesOnDispatched;
131   bool mUpdateCueDisplayDispatched;
132 
133   static StaticRefPtr<nsIWebVTTParserWrapper> sParserWrapper;
134 
135   bool performedTrackSelection;
136 
137   // Runs the algorithm for performing automatic track selection.
138   void HonorUserPreferencesForTrackSelection();
139   // Performs track selection for a single TextTrackKind.
140   void PerformTrackSelection(TextTrackKind aTextTrackKind);
141   // Performs track selection for a set of TextTrackKinds, for example,
142   // 'subtitles' and 'captions' should be selected together.
143   void PerformTrackSelection(TextTrackKind aTextTrackKinds[], uint32_t size);
144   void GetTextTracksOfKinds(TextTrackKind aTextTrackKinds[], uint32_t size,
145                             nsTArray<TextTrack*>& aTextTracks);
146   void GetTextTracksOfKind(TextTrackKind aTextTrackKind,
147                            nsTArray<TextTrack*>& aTextTracks);
148   bool TrackIsDefault(TextTrack* aTextTrack);
149 
150   void ReportTelemetryForTrack(TextTrack* aTextTrack) const;
151 
152   bool IsShutdown() const;
153 
154   // This function will check media element's show poster flag to decide whether
155   // we need to run `TimeMarchesOn`.
156   void MaybeRunTimeMarchesOn();
157 
158   class ShutdownObserverProxy final : public nsIObserver {
159     NS_DECL_ISUPPORTS
160 
161    public:
ShutdownObserverProxy(TextTrackManager * aManager)162     explicit ShutdownObserverProxy(TextTrackManager* aManager)
163         : mManager(aManager) {
164       nsContentUtils::RegisterShutdownObserver(this);
165     }
166 
Observe(nsISupports * aSubject,const char * aTopic,const char16_t * aData)167     NS_IMETHODIMP Observe(nsISupports* aSubject, const char* aTopic,
168                           const char16_t* aData) override {
169       MOZ_ASSERT(NS_IsMainThread());
170       if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
171         if (mManager) {
172           mManager->NotifyShutdown();
173         }
174         Unregister();
175       }
176       return NS_OK;
177     }
178 
179     void Unregister();
180 
181    private:
182     ~ShutdownObserverProxy() = default;
183 
184     TextTrackManager* mManager;
185   };
186 
187   RefPtr<ShutdownObserverProxy> mShutdownProxy;
188   bool mShutdown;
189 };
190 
191 }  // namespace dom
192 }  // namespace mozilla
193 
194 #endif  // mozilla_dom_TextTrackManager_h
195