Issue #2452 - Ensure DOM events aren't dispatched at unexpected time

https://bugzilla.mozilla.org/show_bug.cgi?id=1409985
https://bugzilla.mozilla.org/show_bug.cgi?id=1443746
This commit is contained in:
Martok 2024-01-14 21:51:47 +01:00 • committed by roytam1
commit d6dd1f8133
5 changed files with 53 additions and 6 deletions

View file

@ -5444,6 +5444,14 @@ nsContentUtils::AddPendingIDBTransaction(already_AddRefed<nsIRunnable> aTransact
CycleCollectedJSContext::Get()->AddPendingIDBTransaction(Move(aTransaction));
}
/* static */
bool
nsContentUtils::IsInStableOrMetaStableState()
{
MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!");
return CycleCollectedJSContext::Get()->IsInStableOrMetaStableState();
}
/*
* Helper function for nsContentUtils::ProcessViewportInfo.
*

View file

@ -1779,6 +1779,11 @@ public:
*/
static void AddPendingIDBTransaction(already_AddRefed<nsIRunnable> aTransaction);
/**
* Returns true if we are doing StableState/MetastableState.
*/
static bool IsInStableOrMetaStableState();
/* Process viewport META data. This gives us information for the scale
* and zoom of a page on mobile devices. We stick the information in
* the document header and use it later on after rendering.

View file

@ -693,6 +693,12 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
NS_ENSURE_TRUE(aEvent->mMessage || !aDOMEvent || aTargets,
NS_ERROR_DOM_INVALID_STATE_ERR);
// Events shall not be fired while we are in stable state to prevent anything
// visible from the scripts.
MOZ_ASSERT(!nsContentUtils::IsInStableOrMetaStableState());
NS_ENSURE_TRUE(!nsContentUtils::IsInStableOrMetaStableState(),
NS_ERROR_DOM_INVALID_STATE_ERR);
#ifdef MOZ_TASK_TRACER
{
if (aDOMEvent) {

View file

@ -59,15 +59,30 @@ public:
switch (event) {
case MediaStreamGraphEvent::EVENT_FINISHED:
{
RefPtr<SynthStreamListener> self = this;
if (!mStarted) {
mStarted = true;
nsCOMPtr<nsIRunnable> startRunnable =
NewRunnableMethod(this, &SynthStreamListener::DoNotifyStarted);
nsCOMPtr<nsIRunnable> startRunnable = NS_NewRunnableFunction(
[self] {
// "start" event will be fired in DoNotifyStarted() which is
// not allowed in stable state, so we do it asynchronously in
// next run.
NS_DispatchToMainThread(NewRunnableMethod(
self,
&SynthStreamListener::DoNotifyStarted));
});
aGraph->DispatchToMainThreadAfterStreamStateUpdate(startRunnable.forget());
}
nsCOMPtr<nsIRunnable> endRunnable =
NewRunnableMethod(this, &SynthStreamListener::DoNotifyFinished);
nsCOMPtr<nsIRunnable> endRunnable = NS_NewRunnableFunction(
[self] {
// "end" event will be fired in DoNotifyFinished() which is
// not allowed in stable state, so we do it asynchronously in
// next run.
NS_DispatchToMainThread(NewRunnableMethod(
self,
&SynthStreamListener::DoNotifyFinished));
});
aGraph->DispatchToMainThreadAfterStreamStateUpdate(endRunnable.forget());
}
break;
@ -85,8 +100,16 @@ public:
{
if (aBlocked == MediaStreamListener::UNBLOCKED && !mStarted) {
mStarted = true;
nsCOMPtr<nsIRunnable> event =
NewRunnableMethod(this, &SynthStreamListener::DoNotifyStarted);
RefPtr<SynthStreamListener> self = this;
nsCOMPtr<nsIRunnable> event = NS_NewRunnableFunction(
[self] {
// "start" event will be fired in DoNotifyStarted() which is
// not allowed in stable state, so we do it asynchronously in
// next run.
NS_DispatchToMainThread(NewRunnableMethod(
self,
&SynthStreamListener::DoNotifyStarted));
});
aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
}
}