Skip to content
Permalink
Browse files
Allow Service Workers to run for a little longer in case of functiona…
…l events

https://bugs.webkit.org/show_bug.cgi?id=240454

Patch by Youenn Fablet <youennf@gmail.com> on 2022-05-17
Reviewed by Chris Dumez.

Functional events should usually trigger opening a new web page on the same origin as the service worker.
There are good chances that the service worker will control the new web page, it is thus potentially useful to
keep the service worker around for a bit, to not pay the cost of stopping and restarting it.
To do so, we introduce a timer in SWServerWorker that handles the termination in case of functional events/debugger.

Covered by updated API test.

* Tools/TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm:
* Source/WebCore/workers/service/server/SWServerWorker.cpp:
(WebCore::SWServerWorker::startTermination):
(WebCore::SWServerWorker::shouldBeTerminated const):
(WebCore::SWServerWorker::terminateIfPossible):
(WebCore::SWServerWorker::terminationIfPossibleTimerFired):
* Source/WebCore/workers/service/server/SWServerWorker.h:

Canonical link: https://commits.webkit.org/250635@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@294315 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
youennf authored and webkit-commit-queue committed May 17, 2022
1 parent 074ea00 commit ff2e4e4e8cb42ef46e35ac2e45a86f6143cd0a20
Showing 3 changed files with 39 additions and 1 deletion.
@@ -63,6 +63,7 @@ SWServerWorker::SWServerWorker(SWServer& server, SWServerRegistration& registrat
, m_registrableDomain(m_data.scriptURL)
, m_scriptResourceMap(WTFMove(scriptResourceMap))
, m_terminationTimer(*this, &SWServerWorker::terminationTimerFired)
, m_terminationIfPossibleTimer(*this, &SWServerWorker::terminationIfPossibleTimerFired)
, m_lastNavigationWasAppInitiated(m_server->clientIsAppInitiatedForRegistrableDomain(m_registrableDomain))
{
m_data.scriptURL.removeFragmentIdentifier();
@@ -141,6 +142,7 @@ void SWServerWorker::startTermination(CompletionHandler<void()>&& callback)

m_terminationCallbacks.append(WTFMove(callback));
m_terminationTimer.startOneShot(SWServer::defaultTerminationDelay);
m_terminationIfPossibleTimer.stop();

contextConnection->terminateWorker(identifier());
}
@@ -410,9 +412,24 @@ void SWServerWorker::setAsInspected(bool isInspected)
terminateIfPossible();
}

bool SWServerWorker::shouldBeTerminated() const
{
return !m_functionalEventCounter && !m_isInspected && m_server && !m_server->hasClientsWithOrigin(origin());
}

void SWServerWorker::terminateIfPossible()
{
if (m_functionalEventCounter || m_isInspected || !m_server || m_server->hasClientsWithOrigin(origin()))
if (!shouldBeTerminated()) {
m_terminationIfPossibleTimer.stop();
return;
}

m_terminationIfPossibleTimer.startOneShot(SWServer::defaultFunctionalEventDuration);
}

void SWServerWorker::terminationIfPossibleTimerFired()
{
if (!shouldBeTerminated())
return;

terminate();
@@ -156,8 +156,10 @@ class SWServerWorker : public RefCounted<SWServerWorker> {
void startTermination(CompletionHandler<void()>&&);
void terminationCompleted();
void terminationTimerFired();
void terminationIfPossibleTimerFired();
void callTerminationCallbacks();
void terminateIfPossible();
bool shouldBeTerminated() const;

WeakPtr<SWServer> m_server;
ServiceWorkerRegistrationKey m_registrationKey;
@@ -179,6 +181,7 @@ class SWServerWorker : public RefCounted<SWServerWorker> {
bool m_hasTimedOutAnyFetchTasks { false };
Vector<CompletionHandler<void()>> m_terminationCallbacks;
Timer m_terminationTimer;
Timer m_terminationIfPossibleTimer;
LastNavigationWasAppInitiated m_lastNavigationWasAppInitiated;
int m_functionalEventCounter { 0 };
bool m_isInspected { false };
@@ -393,6 +393,11 @@ static void terminateNetworkProcessWhileRegistrationIsStored(WKWebViewConfigurat
return;
}
if (event.data.text() === 'third') {
if (self.previousMessageData !== 'second')
event.waitUntil(Promise.reject('expected second'));
return;
}
if (event.data.text() === 'fourth') {
if (self.previousMessageData !== undefined)
event.waitUntil(Promise.reject('expected undefined'));
return;
@@ -463,6 +468,19 @@ static void terminateNetworkProcessWhileRegistrationIsStored(WKWebViewConfigurat
pushMessageProcessed = true;
}];
TestWebKitAPI::Util::run(&pushMessageProcessed);
EXPECT_FALSE(pushMessageSuccessful);

// We delay so that the timer to terminate service worker kicks in.
sleep(3);

pushMessageProcessed = false;
pushMessageSuccessful = false;
message = @"fourth";
[[configuration websiteDataStore] _processPushMessage:messageDictionary([message dataUsingEncoding:NSUTF8StringEncoding], [server.request() URL]) completionHandler:^(bool result) {
pushMessageSuccessful = result;
pushMessageProcessed = true;
}];
TestWebKitAPI::Util::run(&pushMessageProcessed);
EXPECT_TRUE(pushMessageSuccessful);
}

0 comments on commit ff2e4e4

Please sign in to comment.