mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1226441 - Part 2: Delay functional event dispatch until service worker is activated; r=catalinb
This commit is contained in:
parent
da0a7ade62
commit
2f321a65d7
@ -4601,6 +4601,7 @@ private:
|
||||
void
|
||||
ServiceWorkerInfo::UpdateState(ServiceWorkerState aState)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
#ifdef DEBUG
|
||||
// Any state can directly transition to redundant, but everything else is
|
||||
// ordered.
|
||||
@ -4613,6 +4614,13 @@ ServiceWorkerInfo::UpdateState(ServiceWorkerState aState)
|
||||
// Activated can only go to redundant.
|
||||
MOZ_ASSERT_IF(mState == ServiceWorkerState::Activated, aState == ServiceWorkerState::Redundant);
|
||||
#endif
|
||||
// Flush any pending functional events to the worker when it transitions to the
|
||||
// activated state.
|
||||
// TODO: Do we care that these events will race with the propagation of the
|
||||
// state change?
|
||||
if (aState == ServiceWorkerState::Activated && mState != aState) {
|
||||
mServiceWorkerPrivate->Activated();
|
||||
}
|
||||
mState = aState;
|
||||
nsCOMPtr<nsIRunnable> r = new ChangeStateUpdater(mInstances, mState);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(r.forget())));
|
||||
|
@ -283,6 +283,7 @@ public:
|
||||
void
|
||||
SetActivateStateUncheckedWithoutEvent(ServiceWorkerState aState)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
mState = aState;
|
||||
}
|
||||
|
||||
|
@ -590,6 +590,14 @@ ServiceWorkerPrivate::SendPushEvent(const Maybe<nsTArray<uint8_t>>& aData,
|
||||
mKeepAliveToken,
|
||||
aData,
|
||||
regInfo);
|
||||
|
||||
if (mInfo->State() == ServiceWorkerState::Activating) {
|
||||
mPendingFunctionalEvents.AppendElement(r.forget());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mInfo->State() == ServiceWorkerState::Activated);
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
|
||||
@ -1057,6 +1065,17 @@ public:
|
||||
return DispatchFetchEvent(aCx, aWorkerPrivate);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Cancel() override
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> runnable = new ResumeRequest(mInterceptedChannel);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
|
||||
NS_WARNING("Failed to resume channel on FetchEventRunnable::Cancel()!\n");
|
||||
}
|
||||
WorkerRunnable::Cancel();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~FetchEventRunnable() {}
|
||||
|
||||
@ -1246,6 +1265,8 @@ ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
|
||||
bool aIsReload)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
// if the ServiceWorker script fails to load for some reason, just resume
|
||||
// the original channel.
|
||||
nsCOMPtr<nsIRunnable> failRunnable =
|
||||
@ -1279,6 +1300,13 @@ ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel,
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mInfo->State() == ServiceWorkerState::Activating) {
|
||||
mPendingFunctionalEvents.AppendElement(r.forget());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mInfo->State() == ServiceWorkerState::Activated);
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
|
||||
@ -1425,6 +1453,15 @@ ServiceWorkerPrivate::TerminateWorker()
|
||||
NS_WARN_IF(!mWorkerPrivate->Terminate(jsapi.cx()));
|
||||
mWorkerPrivate = nullptr;
|
||||
mSupportsArray.Clear();
|
||||
|
||||
// Any pending events are never going to fire on this worker. Cancel
|
||||
// them so that intercepted channels can be reset and other resources
|
||||
// cleaned up.
|
||||
nsTArray<RefPtr<WorkerRunnable>> pendingEvents;
|
||||
mPendingFunctionalEvents.SwapElements(pendingEvents);
|
||||
for (uint32_t i = 0; i < pendingEvents.Length(); ++i) {
|
||||
pendingEvents[i]->Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1447,6 +1484,29 @@ ServiceWorkerPrivate::NoteStoppedControllingDocuments()
|
||||
TerminateWorker();
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerPrivate::Activated()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
// If we had to queue up events due to the worker activating, that means
|
||||
// the worker must be currently running. We should be called synchronously
|
||||
// when the worker becomes activated.
|
||||
MOZ_ASSERT_IF(!mPendingFunctionalEvents.IsEmpty(), mWorkerPrivate);
|
||||
|
||||
nsTArray<RefPtr<WorkerRunnable>> pendingEvents;
|
||||
mPendingFunctionalEvents.SwapElements(pendingEvents);
|
||||
|
||||
for (uint32_t i = 0; i < pendingEvents.Length(); ++i) {
|
||||
RefPtr<WorkerRunnable> r = pendingEvents[i].forget();
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
|
||||
NS_WARNING("Failed to dispatch pending functional event!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ServiceWorkerPrivate::NoteIdleWorkerCallback(nsITimer* aTimer, void* aPrivate)
|
||||
{
|
||||
|
@ -134,6 +134,9 @@ public:
|
||||
return mWorkerPrivate;
|
||||
}
|
||||
|
||||
void
|
||||
Activated();
|
||||
|
||||
private:
|
||||
enum WakeUpReason {
|
||||
FetchEvent = 0,
|
||||
@ -197,6 +200,10 @@ private:
|
||||
// |StoreISupports| and |RemoveISupports|. Note that the array is also
|
||||
// cleared whenever the worker is terminated.
|
||||
nsTArray<nsCOMPtr<nsISupports>> mSupportsArray;
|
||||
|
||||
// Array of function event worker runnables that are pending due to
|
||||
// the worker activating. Main thread only.
|
||||
nsTArray<RefPtr<WorkerRunnable>> mPendingFunctionalEvents;
|
||||
};
|
||||
|
||||
} // namespace workers
|
||||
|
Loading…
Reference in New Issue
Block a user