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