|
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 "WebVTTListener.h" |
|
7 #include "mozilla/dom/TextTrackCue.h" |
|
8 #include "mozilla/dom/TextTrackRegion.h" |
|
9 #include "mozilla/dom/VTTRegionBinding.h" |
|
10 #include "mozilla/dom/HTMLTrackElement.h" |
|
11 #include "nsIInputStream.h" |
|
12 #include "nsIWebVTTParserWrapper.h" |
|
13 #include "nsComponentManagerUtils.h" |
|
14 |
|
15 namespace mozilla { |
|
16 namespace dom { |
|
17 |
|
18 NS_IMPL_CYCLE_COLLECTION(WebVTTListener, mElement, mParserWrapper) |
|
19 |
|
20 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebVTTListener) |
|
21 NS_INTERFACE_MAP_ENTRY(nsIWebVTTListener) |
|
22 NS_INTERFACE_MAP_ENTRY(nsIStreamListener) |
|
23 NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink) |
|
24 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) |
|
25 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebVTTListener) |
|
26 NS_INTERFACE_MAP_END |
|
27 |
|
28 NS_IMPL_CYCLE_COLLECTING_ADDREF(WebVTTListener) |
|
29 NS_IMPL_CYCLE_COLLECTING_RELEASE(WebVTTListener) |
|
30 |
|
31 #ifdef PR_LOGGING |
|
32 PRLogModuleInfo* gTextTrackLog; |
|
33 # define VTT_LOG(...) PR_LOG(gTextTrackLog, PR_LOG_DEBUG, (__VA_ARGS__)) |
|
34 #else |
|
35 # define VTT_LOG(msg) |
|
36 #endif |
|
37 |
|
38 WebVTTListener::WebVTTListener(HTMLTrackElement* aElement) |
|
39 : mElement(aElement) |
|
40 { |
|
41 MOZ_ASSERT(mElement, "Must pass an element to the callback"); |
|
42 #ifdef PR_LOGGING |
|
43 if (!gTextTrackLog) { |
|
44 gTextTrackLog = PR_NewLogModule("TextTrack"); |
|
45 } |
|
46 #endif |
|
47 VTT_LOG("WebVTTListener created."); |
|
48 } |
|
49 |
|
50 WebVTTListener::~WebVTTListener() |
|
51 { |
|
52 VTT_LOG("WebVTTListener destroyed."); |
|
53 } |
|
54 |
|
55 NS_IMETHODIMP |
|
56 WebVTTListener::GetInterface(const nsIID &aIID, |
|
57 void** aResult) |
|
58 { |
|
59 return QueryInterface(aIID, aResult); |
|
60 } |
|
61 |
|
62 nsresult |
|
63 WebVTTListener::LoadResource() |
|
64 { |
|
65 if (!HTMLTrackElement::IsWebVTTEnabled()) { |
|
66 NS_WARNING("WebVTT support disabled." |
|
67 " See media.webvtt.enabled in about:config. "); |
|
68 return NS_ERROR_FAILURE; |
|
69 } |
|
70 nsresult rv; |
|
71 mParserWrapper = do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID, &rv); |
|
72 NS_ENSURE_SUCCESS(rv, rv); |
|
73 |
|
74 nsPIDOMWindow* window = mElement->OwnerDoc()->GetWindow(); |
|
75 rv = mParserWrapper->LoadParser(window); |
|
76 NS_ENSURE_SUCCESS(rv, rv); |
|
77 |
|
78 rv = mParserWrapper->Watch(this); |
|
79 NS_ENSURE_SUCCESS(rv, rv); |
|
80 |
|
81 mElement->SetReadyState(TextTrackReadyState::Loading); |
|
82 return NS_OK; |
|
83 } |
|
84 |
|
85 NS_IMETHODIMP |
|
86 WebVTTListener::AsyncOnChannelRedirect(nsIChannel* aOldChannel, |
|
87 nsIChannel* aNewChannel, |
|
88 uint32_t aFlags, |
|
89 nsIAsyncVerifyRedirectCallback* cb) |
|
90 { |
|
91 if (mElement) { |
|
92 mElement->OnChannelRedirect(aOldChannel, aNewChannel, aFlags); |
|
93 } |
|
94 return NS_OK; |
|
95 } |
|
96 |
|
97 NS_IMETHODIMP |
|
98 WebVTTListener::OnStartRequest(nsIRequest* aRequest, |
|
99 nsISupports* aContext) |
|
100 { |
|
101 return NS_OK; |
|
102 } |
|
103 |
|
104 NS_IMETHODIMP |
|
105 WebVTTListener::OnStopRequest(nsIRequest* aRequest, |
|
106 nsISupports* aContext, |
|
107 nsresult aStatus) |
|
108 { |
|
109 if (NS_FAILED(aStatus)) { |
|
110 mElement->SetReadyState(TextTrackReadyState::FailedToLoad); |
|
111 } |
|
112 // Attempt to parse any final data the parser might still have. |
|
113 mParserWrapper->Flush(); |
|
114 if (mElement->ReadyState() != TextTrackReadyState::FailedToLoad) { |
|
115 mElement->SetReadyState(TextTrackReadyState::Loaded); |
|
116 } |
|
117 return aStatus; |
|
118 } |
|
119 |
|
120 NS_METHOD |
|
121 WebVTTListener::ParseChunk(nsIInputStream* aInStream, void* aClosure, |
|
122 const char* aFromSegment, uint32_t aToOffset, |
|
123 uint32_t aCount, uint32_t* aWriteCount) |
|
124 { |
|
125 nsCString buffer(aFromSegment, aCount); |
|
126 WebVTTListener* listener = static_cast<WebVTTListener*>(aClosure); |
|
127 |
|
128 if (NS_FAILED(listener->mParserWrapper->Parse(buffer))) { |
|
129 VTT_LOG("Unable to parse chunk of WEBVTT text. Aborting."); |
|
130 *aWriteCount = 0; |
|
131 return NS_ERROR_FAILURE; |
|
132 } |
|
133 |
|
134 *aWriteCount = aCount; |
|
135 return NS_OK; |
|
136 } |
|
137 |
|
138 NS_IMETHODIMP |
|
139 WebVTTListener::OnDataAvailable(nsIRequest* aRequest, |
|
140 nsISupports* aContext, |
|
141 nsIInputStream* aStream, |
|
142 uint64_t aOffset, |
|
143 uint32_t aCount) |
|
144 { |
|
145 uint32_t count = aCount; |
|
146 while (count > 0) { |
|
147 uint32_t read; |
|
148 nsresult rv = aStream->ReadSegments(ParseChunk, this, count, &read); |
|
149 NS_ENSURE_SUCCESS(rv, rv); |
|
150 if (!read) { |
|
151 return NS_ERROR_FAILURE; |
|
152 } |
|
153 count -= read; |
|
154 } |
|
155 |
|
156 return NS_OK; |
|
157 } |
|
158 |
|
159 NS_IMETHODIMP |
|
160 WebVTTListener::OnCue(JS::Handle<JS::Value> aCue, JSContext* aCx) |
|
161 { |
|
162 if (!aCue.isObject()) { |
|
163 return NS_ERROR_FAILURE; |
|
164 } |
|
165 |
|
166 TextTrackCue* cue; |
|
167 nsresult rv = UNWRAP_OBJECT(VTTCue, &aCue.toObject(), cue); |
|
168 NS_ENSURE_SUCCESS(rv, rv); |
|
169 |
|
170 cue->SetTrackElement(mElement); |
|
171 mElement->mTrack->AddCue(*cue); |
|
172 |
|
173 return NS_OK; |
|
174 } |
|
175 |
|
176 |
|
177 NS_IMETHODIMP |
|
178 WebVTTListener::OnRegion(JS::Handle<JS::Value> aRegion, JSContext* aCx) |
|
179 { |
|
180 // Nothing for this callback to do. |
|
181 return NS_OK; |
|
182 } |
|
183 |
|
184 NS_IMETHODIMP |
|
185 WebVTTListener::OnParsingError(int32_t errorCode, JSContext* cx) |
|
186 { |
|
187 // We only care about files that have a bad WebVTT file signature right now |
|
188 // as that means the file failed to load. |
|
189 if (errorCode == ErrorCodes::BadSignature) { |
|
190 mElement->SetReadyState(TextTrackReadyState::FailedToLoad); |
|
191 } |
|
192 return NS_OK; |
|
193 } |
|
194 |
|
195 } // namespace dom |
|
196 } // namespace mozilla |