From d6461687812b6eea2555ddd055d431d34f1037d6 Mon Sep 17 00:00:00 2001 From: Rick Eyre Date: Thu, 19 Sep 2013 08:26:00 -0700 Subject: [PATCH] Bug 895091 - Part 2: Add WebVTT parser and wrapper IDls r=rillian, ted, gwagner, khuey - Added vtt.js, a JS WebVTT parser, to Gecko. - Added a wrapper to interface between it and Gecko. - Updated TextTrackCue and WebVTTListener to work with it. --HG-- rename : content/media/WebVTTLoadListener.cpp => content/media/WebVTTListener.cpp rename : content/media/WebVTTLoadListener.h => content/media/WebVTTListener.h --- b2g/installer/package-manifest.in | 3 + browser/installer/package-manifest.in | 3 + content/html/content/src/HTMLTrackElement.cpp | 12 +- content/html/content/src/HTMLTrackElement.h | 11 +- content/media/TextTrackCue.cpp | 37 +++- content/media/TextTrackCue.h | 7 +- content/media/WebVTTListener.cpp | 180 ++++++++++++++++++ content/media/WebVTTListener.h | 60 ++++++ content/media/WebVTTLoadListener.cpp | 141 -------------- content/media/WebVTTLoadListener.h | 72 ------- content/media/moz.build | 13 +- content/media/webvtt/WebVTT.manifest | 3 + content/media/webvtt/WebVTTParserWrapper.js | 62 ++++++ content/media/webvtt/moz.build | 19 ++ content/media/webvtt/nsIWebVTTListener.idl | 29 +++ .../media/webvtt/nsIWebVTTParserWrapper.idl | 66 +++++++ mobile/android/installer/package-manifest.in | 3 + 17 files changed, 487 insertions(+), 234 deletions(-) create mode 100644 content/media/WebVTTListener.cpp create mode 100644 content/media/WebVTTListener.h delete mode 100644 content/media/WebVTTLoadListener.cpp delete mode 100644 content/media/WebVTTLoadListener.h create mode 100644 content/media/webvtt/WebVTT.manifest create mode 100644 content/media/webvtt/WebVTTParserWrapper.js create mode 100644 content/media/webvtt/moz.build create mode 100644 content/media/webvtt/nsIWebVTTListener.idl create mode 100644 content/media/webvtt/nsIWebVTTParserWrapper.idl diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 438d061f5391..7cff24c4e041 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -452,6 +452,9 @@ @BINPATH@/components/SettingsManager.manifest @BINPATH@/components/SettingsService.js @BINPATH@/components/SettingsService.manifest +@BINPATH@/components/webvtt.xpt +@BINPATH@/components/WebVTT.manifest +@BINPATH@/components/WebVTTParserWrapper.js #ifdef MOZ_B2G_RIL @BINPATH@/components/NetworkManager.manifest @BINPATH@/components/NetworkManager.js diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index 806ca67fdbed..f0c2c6aec025 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -375,6 +375,9 @@ @BINPATH@/components/crypto-SDR.js @BINPATH@/components/jsconsole-clhandler.manifest @BINPATH@/components/jsconsole-clhandler.js +@BINPATH@/components/webvtt.xpt +@BINPATH@/components/WebVTT.manifest +@BINPATH@/components/WebVTTParserWrapper.js #ifdef MOZ_GTK @BINPATH@/components/nsFilePicker.manifest @BINPATH@/components/nsFilePicker.js diff --git a/content/html/content/src/HTMLTrackElement.cpp b/content/html/content/src/HTMLTrackElement.cpp index 6f22b742bd75..355f6693ee48 100644 --- a/content/html/content/src/HTMLTrackElement.cpp +++ b/content/html/content/src/HTMLTrackElement.cpp @@ -8,7 +8,7 @@ #include "mozilla/dom/HTMLTrackElement.h" #include "mozilla/dom/HTMLTrackElementBinding.h" #include "mozilla/dom/HTMLUnknownElement.h" -#include "WebVTTLoadListener.h" +#include "WebVTTListener.h" #include "nsAttrValueInlines.h" #include "nsCOMPtr.h" #include "nsContentPolicyUtils.h" @@ -87,7 +87,7 @@ NS_IMPL_RELEASE_INHERITED(HTMLTrackElement, Element) NS_IMPL_CYCLE_COLLECTION_INHERITED_4(HTMLTrackElement, nsGenericHTMLElement, mTrack, mChannel, mMediaParent, - mLoadListener) + mListener) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLTrackElement) NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement) @@ -238,13 +238,13 @@ HTMLTrackElement::LoadResource() channelPolicy); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); - mLoadListener = new WebVTTLoadListener(this); - rv = mLoadListener->LoadResource(); + mListener = new WebVTTListener(this); + rv = mListener->LoadResource(); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); - channel->SetNotificationCallbacks(mLoadListener); + channel->SetNotificationCallbacks(mListener); LOG(PR_LOG_DEBUG, ("opening webvtt channel")); - rv = channel->AsyncOpen(mLoadListener, nullptr); + rv = channel->AsyncOpen(mListener, nullptr); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); mChannel = channel; diff --git a/content/html/content/src/HTMLTrackElement.h b/content/html/content/src/HTMLTrackElement.h index 754f7a55ccd4..3a0f54ee5bd9 100644 --- a/content/html/content/src/HTMLTrackElement.h +++ b/content/html/content/src/HTMLTrackElement.h @@ -31,7 +31,7 @@ static const nsAttrValue::EnumTable kKindTable[] = { { 0 } }; -class WebVTTLoadListener; +class WebVTTListener; class HTMLTrackElement MOZ_FINAL : public nsGenericHTMLElement { @@ -146,18 +146,17 @@ protected: JS::Handle aScope) MOZ_OVERRIDE; void OnChannelRedirect(nsIChannel* aChannel, nsIChannel* aNewChannel, uint32_t aFlags); - // Will open a new channel for the HTMLTrackElement's src attribute and load - // HTMLTrackElement's WebVTTLoadListener by calling WebVTTLoadListener's - // LoadResource(). + // Open a new channel to the HTMLTrackElement's src attribute and call + // mListener's LoadResource(). void LoadResource(); friend class TextTrackCue; - friend class WebVTTLoadListener; + friend class WebVTTListener; nsRefPtr mTrack; nsCOMPtr mChannel; nsRefPtr mMediaParent; - nsRefPtr mLoadListener; + nsRefPtr mListener; uint16_t mReadyState; void CreateTextTrack(); diff --git a/content/media/TextTrackCue.cpp b/content/media/TextTrackCue.cpp index 70fdc3d3cc5b..0f60d79d1c65 100644 --- a/content/media/TextTrackCue.cpp +++ b/content/media/TextTrackCue.cpp @@ -7,6 +7,7 @@ #include "mozilla/dom/TextTrackCue.h" #include "nsIFrame.h" #include "nsVideoFrame.h" +#include "nsComponentManagerUtils.h" // Alternate value for the 'auto' keyword. #define WEBVTT_AUTO -1 @@ -26,6 +27,8 @@ NS_IMPL_RELEASE_INHERITED(TextTrackCue, nsDOMEventTargetHelper) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TextTrackCue) NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) +StaticRefPtr TextTrackCue::sParserWrapper; + // Set cue setting defaults based on step 19 & seq. // in http://dev.w3.org/html5/webvtt/#parsing void @@ -150,9 +153,39 @@ already_AddRefed TextTrackCue::GetCueAsHTML() { MOZ_ASSERT(mDocument); - nsRefPtr frag = mDocument->CreateDocumentFragment(); - return frag.forget(); + if (!sParserWrapper) { + nsresult rv; + nsCOMPtr parserWrapper = + do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID, &rv); + if (NS_FAILED(rv)) { + return mDocument->CreateDocumentFragment(); + } + sParserWrapper = parserWrapper; + } + + nsPIDOMWindow* window = mDocument->GetWindow(); + if (!window) { + return mDocument->CreateDocumentFragment(); + } + + nsCOMPtr div; + sParserWrapper->ConvertCueToDOMTree(window, this, + getter_AddRefs(div)); + if (!div) { + return mDocument->CreateDocumentFragment(); + } + nsRefPtr docFrag = mDocument->CreateDocumentFragment(); + nsCOMPtr throwAway; + docFrag->AppendChild(div, getter_AddRefs(throwAway)); + + return docFrag.forget(); +} + +void +TextTrackCue::SetTrackElement(HTMLTrackElement* aTrackElement) +{ + mTrackElement = aTrackElement; } JSObject* diff --git a/content/media/TextTrackCue.h b/content/media/TextTrackCue.h index 0d518474899e..5dc97c573bb5 100644 --- a/content/media/TextTrackCue.h +++ b/content/media/TextTrackCue.h @@ -11,7 +11,8 @@ #include "mozilla/dom/VTTCueBinding.h" #include "nsCycleCollectionParticipant.h" #include "nsDOMEventTargetHelper.h" -#include "nsIDocument.h" +#include "nsIWebVTTParserWrapper.h" +#include "mozilla/StaticPtr.h" namespace mozilla { namespace dom { @@ -283,6 +284,8 @@ public: */ already_AddRefed GetCueAsHTML(); + void SetTrackElement(HTMLTrackElement* aTrackElement); + private: void CueChanged(); void SetDefaultCueSettings(); @@ -312,6 +315,8 @@ private: // anytime a property that relates to the display of the TextTrackCue is // changed. bool mReset; + + static StaticRefPtr sParserWrapper; }; } // namespace dom diff --git a/content/media/WebVTTListener.cpp b/content/media/WebVTTListener.cpp new file mode 100644 index 000000000000..4343c9d36678 --- /dev/null +++ b/content/media/WebVTTListener.cpp @@ -0,0 +1,180 @@ +/* -*- 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/dom/TextTrackCue.h" +#include "mozilla/dom/HTMLTrackElement.h" +#include "nsIInputStream.h" +#include "nsIWebVTTParserWrapper.h" +#include "nsComponentManagerUtils.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_2(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) + +#ifdef PR_LOGGING +PRLogModuleInfo* gTextTrackLog; +# define LOG(...) PR_LOG(gTextTrackLog, PR_LOG_DEBUG, (__VA_ARGS__)) +#else +# define LOG(msg) +#endif + +WebVTTListener::WebVTTListener(HTMLTrackElement* aElement) + : mElement(aElement) +{ + MOZ_ASSERT(mElement, "Must pass an element to the callback"); +#ifdef PR_LOGGING + if (!gTextTrackLog) { + gTextTrackLog = PR_NewLogModule("TextTrack"); + } +#endif + LOG("WebVTTListener created."); +} + +WebVTTListener::~WebVTTListener() +{ + LOG("WebVTTListener destroyed."); +} + +NS_IMETHODIMP +WebVTTListener::GetInterface(const nsIID &aIID, + void** aResult) +{ + return QueryInterface(aIID, aResult); +} + +nsresult +WebVTTListener::LoadResource() +{ + if (!HTMLTrackElement::IsWebVTTEnabled()) { + NS_WARNING("WebVTT support disabled." + " See media.webvtt.enabled in about:config. "); + return NS_ERROR_FAILURE; + } + nsresult rv; + mParserWrapper = do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsPIDOMWindow* window = mElement->OwnerDoc()->GetWindow(); + rv = mParserWrapper->LoadParser(window); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mParserWrapper->Watch(this); + NS_ENSURE_SUCCESS(rv, rv); + + mElement->mReadyState = HTMLTrackElement::LOADING; + return NS_OK; +} + +NS_IMETHODIMP +WebVTTListener::AsyncOnChannelRedirect(nsIChannel* aOldChannel, + nsIChannel* aNewChannel, + uint32_t aFlags, + nsIAsyncVerifyRedirectCallback* cb) +{ + if (mElement) { + mElement->OnChannelRedirect(aOldChannel, aNewChannel, aFlags); + } + return NS_OK; +} + +NS_IMETHODIMP +WebVTTListener::OnStartRequest(nsIRequest* aRequest, + nsISupports* aContext) +{ + return NS_OK; +} + +NS_IMETHODIMP +WebVTTListener::OnStopRequest(nsIRequest* aRequest, + nsISupports* aContext, + nsresult aStatus) +{ + if (mElement->mReadyState != HTMLTrackElement::ERROR) { + mElement->mReadyState = HTMLTrackElement::LOADED; + } + // Attempt to parse any final data the parser might still have. + mParserWrapper->Flush(); + return NS_OK; +} + +NS_METHOD +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); + + if (NS_FAILED(listener->mParserWrapper->Parse(buffer))) { + LOG("Unable to parse chunk of WEBVTT text. Aborting."); + *aWriteCount = 0; + return NS_ERROR_FAILURE; + } + + *aWriteCount = aCount; + return NS_OK; +} + +NS_IMETHODIMP +WebVTTListener::OnDataAvailable(nsIRequest* aRequest, + nsISupports* aContext, + nsIInputStream* aStream, + uint64_t aOffset, + uint32_t aCount) +{ + 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(const JS::Value &aCue, JSContext* aCx) +{ + if (!aCue.isObject()) { + return NS_ERROR_FAILURE; + } + + TextTrackCue* cue; + nsresult rv = UNWRAP_OBJECT(VTTCue, aCx, &aCue.toObject(), cue); + NS_ENSURE_SUCCESS(rv, rv); + + cue->SetTrackElement(mElement); + mElement->mTrack->AddCue(*cue); + + return NS_OK; +} + + +NS_IMETHODIMP +WebVTTListener::OnRegion(const JS::Value &aRegion, JSContext* aCx) +{ + // TODO: Implement VTTRegions see bug 897504 + return NS_OK; +} + +} // namespace dom +} // namespace mozilla diff --git a/content/media/WebVTTListener.h b/content/media/WebVTTListener.h new file mode 100644 index 000000000000..05df90344876 --- /dev/null +++ b/content/media/WebVTTListener.h @@ -0,0 +1,60 @@ +/* -*- 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/. */ + +#ifndef mozilla_dom_WebVTTLoadListener_h +#define mozilla_dom_WebVTTLoadListener_h + +#include "nsIWebVTTListener.h" +#include "nsIStreamListener.h" +#include "nsIChannelEventSink.h" +#include "nsAutoPtr.h" +#include "nsIInterfaceRequestor.h" +#include "nsCycleCollectionParticipant.h" + +class nsIWebVTTParserWrapper; + +namespace mozilla { +namespace dom { + +class HTMLTrackElement; + +class WebVTTListener MOZ_FINAL : public nsIWebVTTListener, + public nsIStreamListener, + public nsIChannelEventSink, + public nsIInterfaceRequestor +{ + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_NSIWEBVTTLISTENER + NS_DECL_NSIREQUESTOBSERVER + NS_DECL_NSISTREAMLISTENER + NS_DECL_NSICHANNELEVENTSINK + NS_DECL_NSIINTERFACEREQUESTOR + + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(WebVTTListener, + nsIStreamListener) + +public: + WebVTTListener(HTMLTrackElement* aElement); + ~WebVTTListener(); + + /** + * Loads the WebVTTListener. Must call this in order for the listener to be + * ready to parse data that is passed to it. + */ + nsresult LoadResource(); + +private: + static NS_METHOD ParseChunk(nsIInputStream* aInStream, void* aClosure, + const char* aFromSegment, uint32_t aToOffset, + uint32_t aCount, uint32_t* aWriteCount); + + nsRefPtr mElement; + nsCOMPtr mParserWrapper; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_WebVTTListener_h diff --git a/content/media/WebVTTLoadListener.cpp b/content/media/WebVTTLoadListener.cpp deleted file mode 100644 index 27d056176387..000000000000 --- a/content/media/WebVTTLoadListener.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* -*- 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 "WebVTTLoadListener.h" -#include "mozilla/dom/TextTrackCue.h" -#include "mozilla/dom/HTMLTrackElement.h" -#include "nsIInputStream.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_1(WebVTTLoadListener, mElement) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebVTTLoadListener) - NS_INTERFACE_MAP_ENTRY(nsIStreamListener) - NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink) - NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamListener) -NS_INTERFACE_MAP_END - -NS_IMPL_CYCLE_COLLECTING_ADDREF(WebVTTLoadListener) -NS_IMPL_CYCLE_COLLECTING_RELEASE(WebVTTLoadListener) - -#ifdef PR_LOGGING -PRLogModuleInfo* gTextTrackLog; -# define LOG(...) PR_LOG(gTextTrackLog, PR_LOG_DEBUG, (__VA_ARGS__)) -#else -# define LOG(msg) -#endif - -WebVTTLoadListener::WebVTTLoadListener(HTMLTrackElement* aElement) - : mElement(aElement) -{ - MOZ_ASSERT(mElement, "Must pass an element to the callback"); -#ifdef PR_LOGGING - if (!gTextTrackLog) { - gTextTrackLog = PR_NewLogModule("TextTrack"); - } -#endif - LOG("WebVTTLoadListener created."); -} - -WebVTTLoadListener::~WebVTTLoadListener() -{ - LOG("WebVTTLoadListener destroyed."); -} - -nsresult -WebVTTLoadListener::LoadResource() -{ - if (!HTMLTrackElement::IsWebVTTEnabled()) { - NS_WARNING("WebVTT support disabled." - " See media.webvtt.enabled in about:config. "); - return NS_ERROR_FAILURE; - } - - LOG("Loading text track resource."); - - mElement->mReadyState = HTMLTrackElement::LOADING; - return NS_OK; -} - -NS_IMETHODIMP -WebVTTLoadListener::OnStartRequest(nsIRequest* aRequest, - nsISupports* aContext) -{ - return NS_OK; -} - -NS_IMETHODIMP -WebVTTLoadListener::OnStopRequest(nsIRequest* aRequest, - nsISupports* aContext, - nsresult aStatus) -{ - // Flush parser here. - if(mElement->mReadyState != HTMLTrackElement::ERROR) { - mElement->mReadyState = HTMLTrackElement::LOADED; - } - return NS_OK; -} - -NS_IMETHODIMP -WebVTTLoadListener::OnDataAvailable(nsIRequest* aRequest, - nsISupports* aContext, - nsIInputStream* aStream, - uint64_t aOffset, - uint32_t aCount) -{ - 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 -WebVTTLoadListener::AsyncOnChannelRedirect(nsIChannel* aOldChannel, - nsIChannel* aNewChannel, - uint32_t aFlags, - nsIAsyncVerifyRedirectCallback* cb) -{ - if (mElement) { - mElement->OnChannelRedirect(aOldChannel, aNewChannel, aFlags); - } - return NS_OK; -} - -NS_IMETHODIMP -WebVTTLoadListener::GetInterface(const nsIID &aIID, - void** aResult) -{ - return QueryInterface(aIID, aResult); -} - -NS_METHOD -WebVTTLoadListener::ParseChunk(nsIInputStream* aInStream, void* aClosure, - const char* aFromSegment, uint32_t aToOffset, - uint32_t aCount, uint32_t* aWriteCount) -{ - // Call parser incrementally on new data. - if (1) { - LOG("WebVTT parser disabled."); - LOG("Unable to parse chunk of WEBVTT text. Aborting."); - *aWriteCount = 0; - return NS_ERROR_FAILURE; - } - *aWriteCount = aCount; - return NS_OK; -} - -} // namespace dom -} // namespace mozilla diff --git a/content/media/WebVTTLoadListener.h b/content/media/WebVTTLoadListener.h deleted file mode 100644 index b280a627ef69..000000000000 --- a/content/media/WebVTTLoadListener.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_dom_WebVTTLoadListener_h -#define mozilla_dom_WebVTTLoadListener_h - -#include "nsIStreamListener.h" -#include "nsIChannelEventSink.h" -#include "nsIInterfaceRequestor.h" -#include "nsAutoPtr.h" -#include "nsAutoRef.h" -#include "nsCycleCollectionParticipant.h" - -namespace mozilla { -namespace dom { - -class HTMLTrackElement; - -/** - * Class that manages the WebVTT parsing library and functions as an - * interface between Gecko and WebVTT. - * - * Currently it's only designed to work with an HTMLTrackElement. The - * HTMLTrackElement controls the lifetime of the WebVTTLoadListener. - * - * The workflow of this class is as follows: - * - Gets Loaded via an HTMLTrackElement class. - * - As the HTMLTrackElement class gets new data WebVTTLoadListener's - * OnDataAvailable() function is called and data is passed to the WebVTT - * parser. - * - When the WebVTT parser has finished a cue it will call the callbacks - * that are exposed by the WebVTTLoadListener. - * - When it has returned a cue successfully the WebVTTLoadListener will create - * a new TextTrackCue and add it to the HTMLTrackElement's TextTrack. - */ -class WebVTTLoadListener MOZ_FINAL : public nsIStreamListener, - public nsIChannelEventSink, - public nsIInterfaceRequestor -{ - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_NSIREQUESTOBSERVER - NS_DECL_NSISTREAMLISTENER - NS_DECL_NSICHANNELEVENTSINK - NS_DECL_NSIINTERFACEREQUESTOR - - NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(WebVTTLoadListener, - nsIStreamListener) - -public: - WebVTTLoadListener(HTMLTrackElement* aElement); - ~WebVTTLoadListener(); - - // Loads the WebVTT parser. Must call this function in order to the - // WebVTTLoadListener to be ready to accept data. - nsresult LoadResource(); - -private: - static NS_METHOD ParseChunk(nsIInputStream* aInStream, void* aClosure, - const char* aFromSegment, uint32_t aToOffset, - uint32_t aCount, uint32_t* aWriteCount); - - nsRefPtr mElement; -}; - - - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_WebVTTLoadListener_h diff --git a/content/media/moz.build b/content/media/moz.build index 12d48549d319..c6492e73ac42 100644 --- a/content/media/moz.build +++ b/content/media/moz.build @@ -4,11 +4,12 @@ # 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/. -PARALLEL_DIRS += ['encoder'] - -PARALLEL_DIRS += ['mediasource'] - -PARALLEL_DIRS += ['webaudio'] +PARALLEL_DIRS += [ + 'encoder', + 'mediasource', + 'webaudio', + 'webvtt' +] if CONFIG['MOZ_RAW']: PARALLEL_DIRS += ['raw'] @@ -140,7 +141,7 @@ CPP_SOURCES += [ 'VideoSegment.cpp', 'VideoStreamTrack.cpp', 'VideoUtils.cpp', - 'WebVTTLoadListener.cpp', + 'WebVTTListener.cpp', ] FAIL_ON_WARNINGS = True diff --git a/content/media/webvtt/WebVTT.manifest b/content/media/webvtt/WebVTT.manifest new file mode 100644 index 000000000000..40586fbdb4fb --- /dev/null +++ b/content/media/webvtt/WebVTT.manifest @@ -0,0 +1,3 @@ +# WebVTTParserWrapper +component {1604a67f-3b72-4027-bcba-6dddd5be6b10} WebVTTParserWrapper.js +contract @mozilla.org/webvttParserWrapper;1 {1604a67f-3b72-4027-bcba-6dddd5be6b10} diff --git a/content/media/webvtt/WebVTTParserWrapper.js b/content/media/webvtt/WebVTTParserWrapper.js new file mode 100644 index 000000000000..afe2e6692c16 --- /dev/null +++ b/content/media/webvtt/WebVTTParserWrapper.js @@ -0,0 +1,62 @@ +/* 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/. */ + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +// TODO: Import vtt.js + +var Ci = Components.interfaces; + +var WEBVTTPARSERWRAPPER_CID = "{1604a67f-3b72-4027-bcba-6dddd5be6b10}"; +var WEBVTTPARSERWRAPPER_CONTRACTID = "@mozilla.org/webvttParserWrapper;1"; + +function WebVTTParserWrapper() +{ + // Nothing +} + +WebVTTParserWrapper.prototype = +{ + loadParser: function(window) + { + // TODO: Instantiate JS WebVTT parser + }, + + parse: function(data) + { + // We can safely translate the string data to a Uint8Array as we are + // guaranteed character codes only from \u0000 => \u00ff + var buffer = new Uint8Array(data.length); + for (var i = 0; i < data.length; i++) { + buffer[i] = data.charCodeAt(i); + } + + // TODO: Call parse on JS WebVTT parser + }, + + flush: function() + { + // TODO: Call flush on JS WebVTT parser + }, + + watch: function(callback) + { + // TODO: Set callbacks for oncue and onregion for JS WebVTT parser + }, + + convertCueToDOMTree: function(window, cue) + { + // TODO: Call convertCueToDOMTree on JS WebVTT parser + }, + + classDescription: "Wrapper for the JS WebVTTParser (vtt.js)", + classID: Components.ID(WEBVTTPARSERWRAPPER_CID), + QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebVTTParserWrapper]), + classInfo: XPCOMUtils.generateCI({ + classID: WEBVTTPARSERWRAPPER_CID, + contractID: WEBVTTPARSERWRAPPER_CONTRACTID, + interfaces: [Ci.nsIWebVTTParserWrapper] + }) +}; + +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebVTTParserWrapper]); diff --git a/content/media/webvtt/moz.build b/content/media/webvtt/moz.build new file mode 100644 index 000000000000..a0edeeea0730 --- /dev/null +++ b/content/media/webvtt/moz.build @@ -0,0 +1,19 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +XPIDL_SOURCES += [ + 'nsIWebVTTListener.idl', + 'nsIWebVTTParserWrapper.idl', +] + +MODULE = 'webvtt' + +XPIDL_MODULE = 'webvtt' + +EXTRA_COMPONENTS += [ + 'WebVTT.manifest', + 'WebVTTParserWrapper.js', +] diff --git a/content/media/webvtt/nsIWebVTTListener.idl b/content/media/webvtt/nsIWebVTTListener.idl new file mode 100644 index 000000000000..cc2bbbf63ead --- /dev/null +++ b/content/media/webvtt/nsIWebVTTListener.idl @@ -0,0 +1,29 @@ +/* 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 "nsISupports.idl" + +/** + * Listener for a JS WebVTT parser (vtt.js). + */ +[scriptable, uuid(2953cf08-403e-4419-8d20-ce286aac026b)] +interface nsIWebVTTListener : nsISupports +{ + /** + * Is called when the WebVTTParser successfully parses a WebVTT cue. + * + * @param cue An object representing the data of a parsed WebVTT cue. + */ + [implicit_jscontext] + void onCue(in jsval cue); + + /** + * Is called when the WebVTT parser successfully parses a WebVTT region. + * + * @param region An object representing the data of a parsed + * WebVTT region. + */ + [implicit_jscontext] + void onRegion(in jsval region); +}; diff --git a/content/media/webvtt/nsIWebVTTParserWrapper.idl b/content/media/webvtt/nsIWebVTTParserWrapper.idl new file mode 100644 index 000000000000..1fe35f78eb62 --- /dev/null +++ b/content/media/webvtt/nsIWebVTTParserWrapper.idl @@ -0,0 +1,66 @@ +/* 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 "nsISupports.idl" +#include "nsIWebVTTListener.idl" +#include "nsIDOMHTMLElement.idl" + +/** + * Interface for a wrapper of a JS WebVTT parser (vtt.js). + */ +[scriptable, uuid(1604a67f-3b72-4027-bcba-6dddd5be6b10)] +interface nsIWebVTTParserWrapper : nsISupports +{ + /** + * Loads the JS WebVTTParser and sets it to use the passed window to create + * VTTRegions and VTTCues. This function must be called before calling + * parse, flush, or watch. + * + * @param window The window that the parser will use to create VTTCues and + * VTTRegions. + * + */ + void loadParser(in nsIDOMWindow window); + + /** + * Attempts to parse the stream's data as WebVTT format. When it successfully + * parses a WebVTT region or WebVTT cue it will create a VTTRegion or VTTCue + * object and pass it back to the callee through its callbacks. + * + * @param data The buffer that contains the WebVTT data received by the + * Necko consumer so far. + */ + void parse(in ACString data); + + /** + * Flush indicates that no more data is expected from the stream. As such the + * parser should try to parse any kind of partial data it has. + */ + void flush(); + + /** + * Set this parser object to use an nsIWebVTTListener object for its onCue + * and onRegion callbacks. + * + * @param callback The nsIWebVTTListener object that exposes onCue and + * onRegion callbacks for the parser. + */ + void watch(in nsIWebVTTListener callback); + + /** + * Convert the text content of a WebVTT cue to a document fragment so that + * we can display it on the page. + * + * @param window A window object with which the document fragment will be + * created. + * @param cue The cue whose content will be converted to a document + * fragment. + */ + nsIDOMHTMLElement convertCueToDOMTree(in nsIDOMWindow window, + in nsISupports cue); +}; + +%{C++ +#define NS_WEBVTTPARSERWRAPPER_CONTRACTID "@mozilla.org/webvttParserWrapper;1" +%} diff --git a/mobile/android/installer/package-manifest.in b/mobile/android/installer/package-manifest.in index fae766ae7c8c..0e2a51a4ea15 100644 --- a/mobile/android/installer/package-manifest.in +++ b/mobile/android/installer/package-manifest.in @@ -331,6 +331,9 @@ @BINPATH@/components/amContentHandler.js @BINPATH@/components/amWebInstallListener.js @BINPATH@/components/nsBlocklistService.js +@BINPATH@/components/webvtt.xpt +@BINPATH@/components/WebVTT.manifest +@BINPATH@/components/WebVTTParserWrapper.js #ifdef MOZ_UPDATER @BINPATH@/components/nsUpdateService.manifest