From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- dom/media/webvtt/WebVTTListener.cpp | 212 ++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 dom/media/webvtt/WebVTTListener.cpp (limited to 'dom/media/webvtt/WebVTTListener.cpp') diff --git a/dom/media/webvtt/WebVTTListener.cpp b/dom/media/webvtt/WebVTTListener.cpp new file mode 100644 index 0000000000..3f8d99a8f3 --- /dev/null +++ b/dom/media/webvtt/WebVTTListener.cpp @@ -0,0 +1,212 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "WebVTTListener.h" +#include "mozilla/CycleCollectedJSContext.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/HTMLTrackElement.h" +#include "mozilla/dom/TextTrackCue.h" +#include "mozilla/dom/TextTrackRegion.h" +#include "mozilla/dom/VTTRegionBinding.h" +#include "nsComponentManagerUtils.h" +#include "nsIAsyncVerifyRedirectCallback.h" +#include "nsIInputStream.h" + +extern mozilla::LazyLogModule gTextTrackLog; +#define LOG(msg, ...) \ + MOZ_LOG(gTextTrackLog, LogLevel::Debug, \ + ("WebVTTListener=%p, " msg, this, ##__VA_ARGS__)) +#define LOG_WIHTOUT_ADDRESS(msg, ...) \ + MOZ_LOG(gTextTrackLog, LogLevel::Debug, (msg, ##__VA_ARGS__)) + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION(WebVTTListener, mElement, mParserWrapper) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebVTTListener) + NS_INTERFACE_MAP_ENTRY(nsIWebVTTListener) + NS_INTERFACE_MAP_ENTRY(nsIStreamListener) + NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebVTTListener) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(WebVTTListener) +NS_IMPL_CYCLE_COLLECTING_RELEASE(WebVTTListener) + +WebVTTListener::WebVTTListener(HTMLTrackElement* aElement) + : mElement(aElement), mParserWrapperError(NS_OK) { + MOZ_ASSERT(mElement, "Must pass an element to the callback"); + LOG("Created listener for track element %p", aElement); + MOZ_DIAGNOSTIC_ASSERT( + CycleCollectedJSContext::Get() && + !CycleCollectedJSContext::Get()->IsInStableOrMetaStableState()); + mParserWrapper = do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID, + &mParserWrapperError); + if (NS_SUCCEEDED(mParserWrapperError)) { + nsPIDOMWindowInner* window = mElement->OwnerDoc()->GetInnerWindow(); + mParserWrapperError = mParserWrapper->LoadParser(window); + } + if (NS_SUCCEEDED(mParserWrapperError)) { + mParserWrapperError = mParserWrapper->Watch(this); + } +} + +WebVTTListener::~WebVTTListener() { LOG("destroyed."); } + +NS_IMETHODIMP +WebVTTListener::GetInterface(const nsIID& aIID, void** aResult) { + return QueryInterface(aIID, aResult); +} + +nsresult WebVTTListener::LoadResource() { + if (IsCanceled()) { + return NS_OK; + } + // Exit if we failed to create the WebVTTParserWrapper (vtt.jsm) + NS_ENSURE_SUCCESS(mParserWrapperError, mParserWrapperError); + + mElement->SetReadyState(TextTrackReadyState::Loading); + return NS_OK; +} + +NS_IMETHODIMP +WebVTTListener::AsyncOnChannelRedirect(nsIChannel* aOldChannel, + nsIChannel* aNewChannel, uint32_t aFlags, + nsIAsyncVerifyRedirectCallback* cb) { + if (IsCanceled()) { + return NS_OK; + } + if (mElement) { + mElement->OnChannelRedirect(aOldChannel, aNewChannel, aFlags); + } + cb->OnRedirectVerifyCallback(NS_OK); + return NS_OK; +} + +NS_IMETHODIMP +WebVTTListener::OnStartRequest(nsIRequest* aRequest) { + if (IsCanceled()) { + return NS_OK; + } + + LOG("OnStartRequest"); + mElement->DispatchTestEvent(u"mozStartedLoadingTextTrack"_ns); + return NS_OK; +} + +NS_IMETHODIMP +WebVTTListener::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) { + if (IsCanceled()) { + return NS_OK; + } + + LOG("OnStopRequest"); + if (NS_FAILED(aStatus)) { + LOG("Got error status"); + mElement->SetReadyState(TextTrackReadyState::FailedToLoad); + } + // Attempt to parse any final data the parser might still have. + mParserWrapper->Flush(); + if (mElement->ReadyState() != TextTrackReadyState::FailedToLoad) { + mElement->SetReadyState(TextTrackReadyState::Loaded); + } + + mElement->CancelChannelAndListener(); + + return aStatus; +} + +nsresult WebVTTListener::ParseChunk(nsIInputStream* aInStream, void* aClosure, + const char* aFromSegment, + uint32_t aToOffset, uint32_t aCount, + uint32_t* aWriteCount) { + nsCString buffer(aFromSegment, aCount); + WebVTTListener* listener = static_cast(aClosure); + MOZ_ASSERT(!listener->IsCanceled()); + + if (NS_FAILED(listener->mParserWrapper->Parse(buffer))) { + LOG_WIHTOUT_ADDRESS( + "WebVTTListener=%p, Unable to parse chunk of WEBVTT text. Aborting.", + listener); + *aWriteCount = 0; + return NS_ERROR_FAILURE; + } + + *aWriteCount = aCount; + return NS_OK; +} + +NS_IMETHODIMP +WebVTTListener::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aStream, + uint64_t aOffset, uint32_t aCount) { + if (IsCanceled()) { + return NS_OK; + } + + LOG("OnDataAvailable"); + uint32_t count = aCount; + while (count > 0) { + uint32_t read; + nsresult rv = aStream->ReadSegments(ParseChunk, this, count, &read); + NS_ENSURE_SUCCESS(rv, rv); + if (!read) { + return NS_ERROR_FAILURE; + } + count -= read; + } + + return NS_OK; +} + +NS_IMETHODIMP +WebVTTListener::OnCue(JS::Handle aCue, JSContext* aCx) { + MOZ_ASSERT(!IsCanceled()); + if (!aCue.isObject()) { + return NS_ERROR_FAILURE; + } + + JS::Rooted obj(aCx, &aCue.toObject()); + TextTrackCue* cue = nullptr; + nsresult rv = UNWRAP_OBJECT(VTTCue, &obj, cue); + NS_ENSURE_SUCCESS(rv, rv); + + cue->SetTrackElement(mElement); + mElement->mTrack->AddCue(*cue); + + return NS_OK; +} + +NS_IMETHODIMP +WebVTTListener::OnRegion(JS::Handle aRegion, JSContext* aCx) { + MOZ_ASSERT(!IsCanceled()); + // Nothing for this callback to do. + return NS_OK; +} + +NS_IMETHODIMP +WebVTTListener::OnParsingError(int32_t errorCode, JSContext* cx) { + MOZ_ASSERT(!IsCanceled()); + // We only care about files that have a bad WebVTT file signature right now + // as that means the file failed to load. + if (errorCode == ErrorCodes::BadSignature) { + LOG("parsing error"); + mElement->SetReadyState(TextTrackReadyState::FailedToLoad); + } + return NS_OK; +} + +bool WebVTTListener::IsCanceled() const { return mCancel; } + +void WebVTTListener::Cancel() { + MOZ_ASSERT(!IsCanceled(), "Do not cancel canceled listener again!"); + LOG("Cancel listen to channel's response."); + mCancel = true; + mParserWrapper->Cancel(); + mParserWrapper = nullptr; + mElement = nullptr; +} + +} // namespace mozilla::dom -- cgit v1.2.3