Bug 1562021 - part3 : cancel old VTT listener when we start a new load. r=jya,baku

When we start a new load, all previous data fetching from the previous listener and all state changing applied to track element should be ignored.

Therefore, we add a new method `Cancel()` which owner of the listener should call when we would like to discard current listener.

Differential Revision: https://phabricator.services.mozilla.com/D36407

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Alastor Wu 2019-07-03 23:23:29 +00:00
Родитель 53e5ea1cdf
Коммит fd5355860a
5 изменённых файлов: 59 добавлений и 0 удалений

Просмотреть файл

@ -299,9 +299,15 @@ void HTMLTrackElement::LoadResource(RefPtr<WebVTTListener>&& aWebVTTListener) {
if (mChannel) {
mChannel->Cancel(NS_BINDING_ABORTED);
mChannel->SetNotificationCallbacks(nullptr);
mChannel = nullptr;
}
if (mListener) {
mListener->Cancel();
mListener = nullptr;
}
// According to
// https://www.w3.org/TR/html5/embedded-content-0.html#sourcing-out-of-band-text-tracks
//

Просмотреть файл

@ -63,6 +63,9 @@ WebVTTListener::GetInterface(const nsIID& aIID, void** aResult) {
}
nsresult WebVTTListener::LoadResource() {
if (IsCanceled()) {
return NS_OK;
}
// Exit if we failed to create the WebVTTParserWrapper (vtt.jsm)
NS_ENSURE_SUCCESS(mParserWrapperError, mParserWrapperError);
@ -74,6 +77,9 @@ 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);
}
@ -83,12 +89,20 @@ WebVTTListener::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
NS_IMETHODIMP
WebVTTListener::OnStartRequest(nsIRequest* aRequest) {
if (IsCanceled()) {
return NS_OK;
}
LOG("OnStartRequest");
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");
@ -111,6 +125,7 @@ nsresult WebVTTListener::ParseChunk(nsIInputStream* aInStream, void* aClosure,
uint32_t* aWriteCount) {
nsCString buffer(aFromSegment, aCount);
WebVTTListener* listener = static_cast<WebVTTListener*>(aClosure);
MOZ_ASSERT(!listener->IsCanceled());
if (NS_FAILED(listener->mParserWrapper->Parse(buffer))) {
LOG_WIHTOUT_ADDRESS(
@ -127,6 +142,10 @@ nsresult WebVTTListener::ParseChunk(nsIInputStream* aInStream, void* aClosure,
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) {
@ -144,6 +163,7 @@ WebVTTListener::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aStream,
NS_IMETHODIMP
WebVTTListener::OnCue(JS::Handle<JS::Value> aCue, JSContext* aCx) {
MOZ_ASSERT(!IsCanceled());
if (!aCue.isObject()) {
return NS_ERROR_FAILURE;
}
@ -161,12 +181,14 @@ WebVTTListener::OnCue(JS::Handle<JS::Value> aCue, JSContext* aCx) {
NS_IMETHODIMP
WebVTTListener::OnRegion(JS::Handle<JS::Value> 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) {
@ -176,5 +198,16 @@ WebVTTListener::OnParsingError(int32_t errorCode, JSContext* cx) {
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 dom
} // namespace mozilla

Просмотреть файл

@ -42,6 +42,14 @@ class WebVTTListener final : public nsIWebVTTListener,
*/
nsresult LoadResource();
/**
* When this listener is not going to be used anymore, its owner should take
* a responsibility to call `Cancel()` to prevent this listener making any
* changes for the track element.
*/
bool IsCanceled() const;
void Cancel();
private:
~WebVTTListener();
@ -54,6 +62,7 @@ class WebVTTListener final : public nsIWebVTTListener,
RefPtr<HTMLTrackElement> mElement;
nsCOMPtr<nsIWebVTTParserWrapper> mParserWrapper;
nsresult mParserWrapperError;
bool mCancel = false;
};
} // namespace dom

Просмотреть файл

@ -43,6 +43,12 @@ WebVTTParserWrapper.prototype =
};
},
cancel: function() {
this.parser.oncue = null;
this.parser.onregion = null;
this.parser.onparsingerror = null;
},
convertCueToDOMTree: function(window, cue)
{
return WebVTT.convertCueToDOMTree(window, cue.text);

Просмотреть файл

@ -52,6 +52,11 @@ interface nsIWebVTTParserWrapper : nsISupports
*/
void watch(in nsIWebVTTListener callback);
/**
* Cancel watching notifications which parser would send.
*/
void cancel();
/**
* Convert the text content of a WebVTT cue to a document fragment so that
* we can display it on the page.