1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/WebVTTListener.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,196 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "WebVTTListener.h" 1.10 +#include "mozilla/dom/TextTrackCue.h" 1.11 +#include "mozilla/dom/TextTrackRegion.h" 1.12 +#include "mozilla/dom/VTTRegionBinding.h" 1.13 +#include "mozilla/dom/HTMLTrackElement.h" 1.14 +#include "nsIInputStream.h" 1.15 +#include "nsIWebVTTParserWrapper.h" 1.16 +#include "nsComponentManagerUtils.h" 1.17 + 1.18 +namespace mozilla { 1.19 +namespace dom { 1.20 + 1.21 +NS_IMPL_CYCLE_COLLECTION(WebVTTListener, mElement, mParserWrapper) 1.22 + 1.23 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebVTTListener) 1.24 + NS_INTERFACE_MAP_ENTRY(nsIWebVTTListener) 1.25 + NS_INTERFACE_MAP_ENTRY(nsIStreamListener) 1.26 + NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink) 1.27 + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) 1.28 + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebVTTListener) 1.29 +NS_INTERFACE_MAP_END 1.30 + 1.31 +NS_IMPL_CYCLE_COLLECTING_ADDREF(WebVTTListener) 1.32 +NS_IMPL_CYCLE_COLLECTING_RELEASE(WebVTTListener) 1.33 + 1.34 +#ifdef PR_LOGGING 1.35 +PRLogModuleInfo* gTextTrackLog; 1.36 +# define VTT_LOG(...) PR_LOG(gTextTrackLog, PR_LOG_DEBUG, (__VA_ARGS__)) 1.37 +#else 1.38 +# define VTT_LOG(msg) 1.39 +#endif 1.40 + 1.41 +WebVTTListener::WebVTTListener(HTMLTrackElement* aElement) 1.42 + : mElement(aElement) 1.43 +{ 1.44 + MOZ_ASSERT(mElement, "Must pass an element to the callback"); 1.45 +#ifdef PR_LOGGING 1.46 + if (!gTextTrackLog) { 1.47 + gTextTrackLog = PR_NewLogModule("TextTrack"); 1.48 + } 1.49 +#endif 1.50 + VTT_LOG("WebVTTListener created."); 1.51 +} 1.52 + 1.53 +WebVTTListener::~WebVTTListener() 1.54 +{ 1.55 + VTT_LOG("WebVTTListener destroyed."); 1.56 +} 1.57 + 1.58 +NS_IMETHODIMP 1.59 +WebVTTListener::GetInterface(const nsIID &aIID, 1.60 + void** aResult) 1.61 +{ 1.62 + return QueryInterface(aIID, aResult); 1.63 +} 1.64 + 1.65 +nsresult 1.66 +WebVTTListener::LoadResource() 1.67 +{ 1.68 + if (!HTMLTrackElement::IsWebVTTEnabled()) { 1.69 + NS_WARNING("WebVTT support disabled." 1.70 + " See media.webvtt.enabled in about:config. "); 1.71 + return NS_ERROR_FAILURE; 1.72 + } 1.73 + nsresult rv; 1.74 + mParserWrapper = do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID, &rv); 1.75 + NS_ENSURE_SUCCESS(rv, rv); 1.76 + 1.77 + nsPIDOMWindow* window = mElement->OwnerDoc()->GetWindow(); 1.78 + rv = mParserWrapper->LoadParser(window); 1.79 + NS_ENSURE_SUCCESS(rv, rv); 1.80 + 1.81 + rv = mParserWrapper->Watch(this); 1.82 + NS_ENSURE_SUCCESS(rv, rv); 1.83 + 1.84 + mElement->SetReadyState(TextTrackReadyState::Loading); 1.85 + return NS_OK; 1.86 +} 1.87 + 1.88 +NS_IMETHODIMP 1.89 +WebVTTListener::AsyncOnChannelRedirect(nsIChannel* aOldChannel, 1.90 + nsIChannel* aNewChannel, 1.91 + uint32_t aFlags, 1.92 + nsIAsyncVerifyRedirectCallback* cb) 1.93 +{ 1.94 + if (mElement) { 1.95 + mElement->OnChannelRedirect(aOldChannel, aNewChannel, aFlags); 1.96 + } 1.97 + return NS_OK; 1.98 +} 1.99 + 1.100 +NS_IMETHODIMP 1.101 +WebVTTListener::OnStartRequest(nsIRequest* aRequest, 1.102 + nsISupports* aContext) 1.103 +{ 1.104 + return NS_OK; 1.105 +} 1.106 + 1.107 +NS_IMETHODIMP 1.108 +WebVTTListener::OnStopRequest(nsIRequest* aRequest, 1.109 + nsISupports* aContext, 1.110 + nsresult aStatus) 1.111 +{ 1.112 + if (NS_FAILED(aStatus)) { 1.113 + mElement->SetReadyState(TextTrackReadyState::FailedToLoad); 1.114 + } 1.115 + // Attempt to parse any final data the parser might still have. 1.116 + mParserWrapper->Flush(); 1.117 + if (mElement->ReadyState() != TextTrackReadyState::FailedToLoad) { 1.118 + mElement->SetReadyState(TextTrackReadyState::Loaded); 1.119 + } 1.120 + return aStatus; 1.121 +} 1.122 + 1.123 +NS_METHOD 1.124 +WebVTTListener::ParseChunk(nsIInputStream* aInStream, void* aClosure, 1.125 + const char* aFromSegment, uint32_t aToOffset, 1.126 + uint32_t aCount, uint32_t* aWriteCount) 1.127 +{ 1.128 + nsCString buffer(aFromSegment, aCount); 1.129 + WebVTTListener* listener = static_cast<WebVTTListener*>(aClosure); 1.130 + 1.131 + if (NS_FAILED(listener->mParserWrapper->Parse(buffer))) { 1.132 + VTT_LOG("Unable to parse chunk of WEBVTT text. Aborting."); 1.133 + *aWriteCount = 0; 1.134 + return NS_ERROR_FAILURE; 1.135 + } 1.136 + 1.137 + *aWriteCount = aCount; 1.138 + return NS_OK; 1.139 +} 1.140 + 1.141 +NS_IMETHODIMP 1.142 +WebVTTListener::OnDataAvailable(nsIRequest* aRequest, 1.143 + nsISupports* aContext, 1.144 + nsIInputStream* aStream, 1.145 + uint64_t aOffset, 1.146 + uint32_t aCount) 1.147 +{ 1.148 + uint32_t count = aCount; 1.149 + while (count > 0) { 1.150 + uint32_t read; 1.151 + nsresult rv = aStream->ReadSegments(ParseChunk, this, count, &read); 1.152 + NS_ENSURE_SUCCESS(rv, rv); 1.153 + if (!read) { 1.154 + return NS_ERROR_FAILURE; 1.155 + } 1.156 + count -= read; 1.157 + } 1.158 + 1.159 + return NS_OK; 1.160 +} 1.161 + 1.162 +NS_IMETHODIMP 1.163 +WebVTTListener::OnCue(JS::Handle<JS::Value> aCue, JSContext* aCx) 1.164 +{ 1.165 + if (!aCue.isObject()) { 1.166 + return NS_ERROR_FAILURE; 1.167 + } 1.168 + 1.169 + TextTrackCue* cue; 1.170 + nsresult rv = UNWRAP_OBJECT(VTTCue, &aCue.toObject(), cue); 1.171 + NS_ENSURE_SUCCESS(rv, rv); 1.172 + 1.173 + cue->SetTrackElement(mElement); 1.174 + mElement->mTrack->AddCue(*cue); 1.175 + 1.176 + return NS_OK; 1.177 +} 1.178 + 1.179 + 1.180 +NS_IMETHODIMP 1.181 +WebVTTListener::OnRegion(JS::Handle<JS::Value> aRegion, JSContext* aCx) 1.182 +{ 1.183 + // Nothing for this callback to do. 1.184 + return NS_OK; 1.185 +} 1.186 + 1.187 +NS_IMETHODIMP 1.188 +WebVTTListener::OnParsingError(int32_t errorCode, JSContext* cx) 1.189 +{ 1.190 + // We only care about files that have a bad WebVTT file signature right now 1.191 + // as that means the file failed to load. 1.192 + if (errorCode == ErrorCodes::BadSignature) { 1.193 + mElement->SetReadyState(TextTrackReadyState::FailedToLoad); 1.194 + } 1.195 + return NS_OK; 1.196 +} 1.197 + 1.198 +} // namespace dom 1.199 +} // namespace mozilla