Bug 1941046 - Part 4: Send a callback request for impression and clicks of MARS Top...
[gecko.git] / dom / media / webvtt / WebVTTListener.cpp
blob5cdef78dd1f7a1ae1a336adee79908703c754dbe
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/. */
6 #include "WebVTTListener.h"
7 #include "mozilla/CycleCollectedJSContext.h"
8 #include "mozilla/dom/Document.h"
9 #include "mozilla/dom/HTMLTrackElement.h"
10 #include "mozilla/dom/TextTrackCue.h"
11 #include "mozilla/dom/TextTrackRegion.h"
12 #include "mozilla/dom/VTTRegionBinding.h"
13 #include "nsComponentManagerUtils.h"
14 #include "nsIAsyncVerifyRedirectCallback.h"
15 #include "nsIInputStream.h"
17 extern mozilla::LazyLogModule gTextTrackLog;
18 #define LOG(msg, ...) \
19 MOZ_LOG(gTextTrackLog, LogLevel::Debug, \
20 ("WebVTTListener=%p, " msg, this, ##__VA_ARGS__))
21 #define LOG_WIHTOUT_ADDRESS(msg, ...) \
22 MOZ_LOG(gTextTrackLog, LogLevel::Debug, (msg, ##__VA_ARGS__))
24 namespace mozilla::dom {
26 NS_IMPL_CYCLE_COLLECTION(WebVTTListener, mElement, mParserWrapper)
28 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebVTTListener)
29 NS_INTERFACE_MAP_ENTRY(nsIWebVTTListener)
30 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
31 NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
32 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
33 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebVTTListener)
34 NS_INTERFACE_MAP_END
36 NS_IMPL_CYCLE_COLLECTING_ADDREF(WebVTTListener)
37 NS_IMPL_CYCLE_COLLECTING_RELEASE(WebVTTListener)
39 WebVTTListener::WebVTTListener(HTMLTrackElement* aElement)
40 : mElement(aElement), mParserWrapperError(NS_OK) {
41 MOZ_ASSERT(mElement, "Must pass an element to the callback");
42 LOG("Created listener for track element %p", aElement);
43 MOZ_DIAGNOSTIC_ASSERT(
44 CycleCollectedJSContext::Get() &&
45 !CycleCollectedJSContext::Get()->IsInStableOrMetaStableState());
46 mParserWrapper = do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID,
47 &mParserWrapperError);
48 if (NS_SUCCEEDED(mParserWrapperError)) {
49 nsPIDOMWindowInner* window = mElement->OwnerDoc()->GetInnerWindow();
50 mParserWrapperError = mParserWrapper->LoadParser(window);
52 if (NS_SUCCEEDED(mParserWrapperError)) {
53 mParserWrapperError = mParserWrapper->Watch(this);
57 WebVTTListener::~WebVTTListener() { LOG("destroyed."); }
59 NS_IMETHODIMP
60 WebVTTListener::GetInterface(const nsIID& aIID, void** aResult) {
61 return QueryInterface(aIID, aResult);
64 nsresult WebVTTListener::LoadResource() {
65 if (IsCanceled()) {
66 return NS_OK;
68 // Exit if we failed to create the WebVTTParserWrapper (vtt.sys.mjs)
69 NS_ENSURE_SUCCESS(mParserWrapperError, mParserWrapperError);
71 mElement->SetReadyState(TextTrackReadyState::Loading);
72 return NS_OK;
75 NS_IMETHODIMP
76 WebVTTListener::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
77 nsIChannel* aNewChannel, uint32_t aFlags,
78 nsIAsyncVerifyRedirectCallback* cb) {
79 if (IsCanceled()) {
80 return NS_OK;
82 if (mElement) {
83 mElement->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
85 cb->OnRedirectVerifyCallback(NS_OK);
86 return NS_OK;
89 NS_IMETHODIMP
90 WebVTTListener::OnStartRequest(nsIRequest* aRequest) {
91 if (IsCanceled()) {
92 return NS_OK;
95 LOG("OnStartRequest");
96 mElement->DispatchTestEvent(u"mozStartedLoadingTextTrack"_ns);
97 return NS_OK;
100 NS_IMETHODIMP
101 WebVTTListener::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) {
102 if (IsCanceled()) {
103 return NS_OK;
106 LOG("OnStopRequest");
107 if (NS_FAILED(aStatus)) {
108 LOG("Got error status");
109 mElement->SetReadyState(TextTrackReadyState::FailedToLoad);
111 // Attempt to parse any final data the parser might still have.
112 mParserWrapper->Flush();
113 if (mElement->ReadyState() != TextTrackReadyState::FailedToLoad) {
114 mElement->SetReadyState(TextTrackReadyState::Loaded);
117 // Prevent canceling the channel and listener if RFP is enabled.
118 mElement->CancelChannelAndListener(true);
120 return aStatus;
123 nsresult WebVTTListener::ParseChunk(nsIInputStream* aInStream, void* aClosure,
124 const char* aFromSegment,
125 uint32_t aToOffset, uint32_t aCount,
126 uint32_t* aWriteCount) {
127 nsCString buffer(aFromSegment, aCount);
128 WebVTTListener* listener = static_cast<WebVTTListener*>(aClosure);
129 MOZ_ASSERT(!listener->IsCanceled());
131 if (NS_FAILED(listener->mParserWrapper->Parse(buffer))) {
132 LOG_WIHTOUT_ADDRESS(
133 "WebVTTListener=%p, Unable to parse chunk of WEBVTT text. Aborting.",
134 listener);
135 *aWriteCount = 0;
136 return NS_ERROR_FAILURE;
139 *aWriteCount = aCount;
140 return NS_OK;
143 NS_IMETHODIMP
144 WebVTTListener::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aStream,
145 uint64_t aOffset, uint32_t aCount) {
146 if (IsCanceled()) {
147 return NS_OK;
150 LOG("OnDataAvailable");
151 uint32_t count = aCount;
152 while (count > 0) {
153 uint32_t read;
154 nsresult rv = aStream->ReadSegments(ParseChunk, this, count, &read);
155 NS_ENSURE_SUCCESS(rv, rv);
156 if (!read) {
157 return NS_ERROR_FAILURE;
159 count -= read;
162 return NS_OK;
165 NS_IMETHODIMP
166 WebVTTListener::OnCue(JS::Handle<JS::Value> aCue, JSContext* aCx) {
167 MOZ_ASSERT(!IsCanceled());
168 if (!aCue.isObject()) {
169 return NS_ERROR_FAILURE;
172 JS::Rooted<JSObject*> obj(aCx, &aCue.toObject());
173 TextTrackCue* cue = nullptr;
174 nsresult rv = UNWRAP_OBJECT(VTTCue, &obj, cue);
175 NS_ENSURE_SUCCESS(rv, rv);
177 cue->SetTrackElement(mElement);
178 mElement->mTrack->AddCue(*cue);
180 return NS_OK;
183 NS_IMETHODIMP
184 WebVTTListener::OnRegion(JS::Handle<JS::Value> aRegion, JSContext* aCx) {
185 MOZ_ASSERT(!IsCanceled());
186 // Nothing for this callback to do.
187 return NS_OK;
190 NS_IMETHODIMP
191 WebVTTListener::OnParsingError(int32_t errorCode, JSContext* cx) {
192 MOZ_ASSERT(!IsCanceled());
193 // We only care about files that have a bad WebVTT file signature right now
194 // as that means the file failed to load.
195 if (errorCode == ErrorCodes::BadSignature) {
196 LOG("parsing error");
197 mElement->SetReadyState(TextTrackReadyState::FailedToLoad);
199 return NS_OK;
202 bool WebVTTListener::IsCanceled() const { return mCancel; }
204 void WebVTTListener::Cancel() {
205 MOZ_ASSERT(!IsCanceled(), "Do not cancel canceled listener again!");
206 LOG("Cancel listen to channel's response.");
207 mCancel = true;
208 mParserWrapper->Cancel();
209 mParserWrapper = nullptr;
210 mElement = nullptr;
213 } // namespace mozilla::dom