Issue #2452 - Don't use WebVTTListener, JS wrapper, MediaShutdownManager in stable state

https://bugzilla.mozilla.org/show_bug.cgi?id=1443429
https://bugzilla.mozilla.org/show_bug.cgi?id=1515021
This commit is contained in:
Martok 2024-01-14 22:41:18 +01:00 • committed by roytam1
commit fbd829908e
7 changed files with 77 additions and 38 deletions

View file

@ -53,6 +53,7 @@
#include "MediaDecoder.h"
#include "MediaPrefs.h"
#include "MediaResource.h"
#include "MediaShutdownManager.h"
#include "nsICategoryManager.h"
#include "nsIContentPolicy.h"
@ -3217,6 +3218,13 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
NotifyOwnerDocumentActivityChanged();
MOZ_ASSERT(NS_IsMainThread());
// We initialize the MediaShutdownManager as the HTMLMediaElement is always
// constructed on the main thread, and not during stable state.
// (MediaShutdownManager make use of nsIAsyncShutdownClient which is written
// in JS)
MediaShutdownManager::InitStatics();
mWatchManager.Watch(mDownloadSuspendedByCache, &HTMLMediaElement::UpdateReadyStateInternal);
// Paradoxically, there is a self-edge whereby UpdateReadyStateInternal refuses
// to run until mReadyState reaches at least HAVE_METADATA by some other means.

View file

@ -264,14 +264,16 @@ void
HTMLTrackElement::DispatchLoadResource()
{
if (!mLoadResourceDispatched) {
RefPtr<Runnable> r = NewRunnableMethod(this, &HTMLTrackElement::LoadResource);
RefPtr<WebVTTListener> listener = new WebVTTListener(this);
RefPtr<Runnable> r = NewRunnableMethod<RefPtr<WebVTTListener>>(this,
&HTMLTrackElement::LoadResource, std::move(listener));
nsContentUtils::RunInStableState(r.forget());
mLoadResourceDispatched = true;
}
}
void
HTMLTrackElement::LoadResource()
HTMLTrackElement::LoadResource(RefPtr<WebVTTListener>&& aWebVTTListener)
{
mLoadResourceDispatched = false;
@ -317,33 +319,46 @@ HTMLTrackElement::LoadResource()
}
}
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsILoadGroup> loadGroup = OwnerDoc()->GetDocumentLoadGroup();
rv = NS_NewChannel(getter_AddRefs(channel),
uri,
static_cast<Element*>(this),
secFlags,
nsIContentPolicy::TYPE_INTERNAL_TRACK,
loadGroup,
nullptr, // aCallbacks
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI);
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));
mListener = new WebVTTListener(this);
mListener = std::move(aWebVTTListener);
// This will do 6. Set the text track readiness state to loading.
rv = mListener->LoadResource();
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));
channel->SetNotificationCallbacks(mListener);
LOG(LogLevel::Debug, ("opening webvtt channel"));
rv = channel->AsyncOpen2(mListener);
if (NS_FAILED(rv)) {
SetReadyState(TextTrackReadyState::FailedToLoad);
nsIDocument* doc = OwnerDoc();
if (!doc) {
return;
}
mChannel = channel;
// 9. End the synchronous section, continuing the remaining steps in parallel.
NS_DispatchToMainThread(NS_NewRunnableFunction(
[ self = RefPtr<HTMLTrackElement>(this), uri, secFlags ]() {
if (!self->mListener) {
// Shutdown got called, abort.
return;
}
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsILoadGroup> loadGroup = self->OwnerDoc()->GetDocumentLoadGroup();
nsresult rv = NS_NewChannel(getter_AddRefs(channel),
uri,
static_cast<Element*>(self),
secFlags,
nsIContentPolicy::TYPE_INTERNAL_TRACK,
loadGroup,
nullptr, // aCallbacks
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI);
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));
channel->SetNotificationCallbacks(self->mListener);
LOG(LogLevel::Debug, ("opening webvtt channel"));
rv = channel->AsyncOpen2(self->mListener);
if (NS_FAILED(rv)) {
self->SetReadyState(TextTrackReadyState::FailedToLoad);
return;
}
self->mChannel = channel;
}));
}
nsresult

View file

@ -118,9 +118,6 @@ protected:
virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
void OnChannelRedirect(nsIChannel* aChannel, nsIChannel* aNewChannel,
uint32_t aFlags);
// Open a new channel to the HTMLTrackElement's src attribute and call
// mListener's LoadResource().
void LoadResource();
friend class TextTrackCue;
friend class WebVTTListener;
@ -134,6 +131,9 @@ protected:
private:
void DispatchLoadResource();
// Open a new channel to the HTMLTrackElement's src attribute and call
// mListener's LoadResource().
void LoadResource(RefPtr<WebVTTListener>&& aWebVTTListener);
bool mLoadResourceDispatched;
RefPtr<WindowDestroyObserver> mWindowDestroyObserver;

View file

@ -602,6 +602,17 @@ void
TextTrackManager::TimeMarchesOn()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
CycleCollectedJSContext* context = CycleCollectedJSContext::Get();
if (context && context->IsInStableOrMetaStableState()) {
// FireTimeUpdate can be called while at stable state following a
// current position change which triggered a state watcher in MediaDecoder
// (see bug 1443429).
// TimeMarchesOn() will modify JS attributes which is forbidden while in
// stable state. So we dispatch a task to perform such operation later
// instead.
DispatchTimeMarchesOn();
return;
}
WEBVTT_LOG("TimeMarchesOn");
mTimeMarchesOnDispatched = false;