Diff
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (293505 => 293506)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2022-04-27 13:12:28 UTC (rev 293506)
@@ -1,5 +1,14 @@
2022-04-27 Youenn Fablet <[email protected]>
+ service worker update should refresh imported scripts in addition to the main script
+ https://bugs.webkit.org/show_bug.cgi?id=239657
+
+ Reviewed by Chris Dumez.
+
+ * web-platform-tests/service-workers/service-worker/credentials.https-expected.txt:
+
+2022-04-27 Youenn Fablet <[email protected]>
+
Shared workers should match service worker registrations
https://bugs.webkit.org/show_bug.cgi?id=239122
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/credentials.https-expected.txt (293505 => 293506)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/credentials.https-expected.txt 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/credentials.https-expected.txt 2022-04-27 13:12:28 UTC (rev 293506)
@@ -1,7 +1,7 @@
PASS Set cookies as initialization
PASS Main script should have credentials
-FAIL Imported script should have credentials promise_test: Unhandled rejection with value: object "TypeError: null is not an object (evaluating 'worker.postMessage')"
-FAIL Module with an imported statement should not have credentials promise_test: Unhandled rejection with value: object "TypeError: null is not an object (evaluating 'worker.postMessage')"
+PASS Imported script should have credentials
+PASS Module with an imported statement should not have credentials
FAIL Script with service worker served as modules should not have credentials assert_equals: new module worker should not have credentials expected (undefined) undefined but got (string) "1"
Modified: trunk/Source/WebCore/ChangeLog (293505 => 293506)
--- trunk/Source/WebCore/ChangeLog 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebCore/ChangeLog 2022-04-27 13:12:28 UTC (rev 293506)
@@ -1,3 +1,31 @@
+2022-04-27 Youenn Fablet <[email protected]>
+
+ service worker update should refresh imported scripts in addition to the main script
+ https://bugs.webkit.org/show_bug.cgi?id=239657
+
+ Reviewed by Chris Dumez.
+
+ After checking main script, if matching, we refreach each identified imported script.
+ If matching, we reuse the same worker, otherwise we install a new one.
+ We reuse the soft update loader to fetch scripts in case of soft update.
+ Otherwise, we load scripts through the job's client.
+
+ Covered by rebased test.
+
+ * workers/service/SWClientConnection.cpp:
+ * workers/service/SWClientConnection.h:
+ * workers/service/ServiceWorkerContainer.cpp:
+ * workers/service/ServiceWorkerContainer.h:
+ * workers/service/ServiceWorkerJob.cpp:
+ * workers/service/ServiceWorkerJob.h:
+ * workers/service/ServiceWorkerJobClient.h:
+ * workers/service/server/SWServer.cpp:
+ * workers/service/server/SWServer.h:
+ * workers/service/server/SWServerJobQueue.cpp:
+ * workers/service/server/SWServerJobQueue.h:
+ * workers/service/server/SWServerWorker.cpp:
+ * workers/service/server/SWServerWorker.h:
+
2022-04-27 Nikolas Zimmermann <[email protected]>
[LBSE] Fix origin of transformations in SVG
Modified: trunk/Source/WebCore/workers/service/SWClientConnection.cpp (293505 => 293506)
--- trunk/Source/WebCore/workers/service/SWClientConnection.cpp 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebCore/workers/service/SWClientConnection.cpp 2022-04-27 13:12:28 UTC (rev 293506)
@@ -115,7 +115,46 @@
finishFetchingScriptInServer({ serverConnectionIdentifier(), jobIdentifier }, WTFMove(registrationKey), workerFetchError(ResourceError { errorDomainWebKitInternal, 0, { }, makeString("Failed to fetch script for service worker with scope ", registrationKey.scope().string()) }));
}
+class RefreshImportedScriptsCallbackHandler {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ explicit RefreshImportedScriptsCallbackHandler(ServiceWorkerJob::RefreshImportedScriptsCallback&& callback)
+ : m_callback(WTFMove(callback))
+ {
+ }
+ ~RefreshImportedScriptsCallbackHandler()
+ {
+ if (!m_callback)
+ return;
+
+ callOnMainThread([callback = WTFMove(m_callback)] () mutable {
+ callback({ });
+ });
+ }
+
+ void call(Vector<std::pair<URL, ScriptBuffer>>&& scripts)
+ {
+ callOnMainThread([callback = WTFMove(m_callback), scripts = crossThreadCopy(WTFMove(scripts))] () mutable {
+ callback(WTFMove(scripts));
+ });
+ }
+
+private:
+ ServiceWorkerJob::RefreshImportedScriptsCallback m_callback;
+};
+
+void SWClientConnection::refreshImportedScripts(ServiceWorkerJobIdentifier jobIdentifier, FetchOptions::Cache cachePolicy, Vector<URL>&& urls, ServiceWorkerJob::RefreshImportedScriptsCallback&& callback)
+{
+ ASSERT(isMainThread());
+ auto handler = makeUnique<RefreshImportedScriptsCallbackHandler>(WTFMove(callback));
+ postTaskForJob(jobIdentifier, IsJobComplete::No, [cachePolicy, urls = crossThreadCopy(WTFMove(urls)), handler = WTFMove(handler)] (auto& job) mutable {
+ job.refreshImportedScripts(urls, cachePolicy, [handler = WTFMove(handler)] (auto&& result) {
+ handler->call(WTFMove(result));
+ });
+ });
+}
+
static void postMessageToContainer(ScriptExecutionContext& context, MessageWithMessagePorts&& message, ServiceWorkerData&& sourceData, String&& sourceOrigin)
{
if (auto* container = context.ensureServiceWorkerContainer())
Modified: trunk/Source/WebCore/workers/service/SWClientConnection.h (293505 => 293506)
--- trunk/Source/WebCore/workers/service/SWClientConnection.h 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebCore/workers/service/SWClientConnection.h 2022-04-27 13:12:28 UTC (rev 293506)
@@ -124,6 +124,7 @@
WEBCORE_EXPORT void jobRejectedInServer(ServiceWorkerJobIdentifier, ExceptionData&&);
WEBCORE_EXPORT void registrationJobResolvedInServer(ServiceWorkerJobIdentifier, ServiceWorkerRegistrationData&&, ShouldNotifyWhenResolved);
WEBCORE_EXPORT void startScriptFetchForServer(ServiceWorkerJobIdentifier, ServiceWorkerRegistrationKey&&, FetchOptions::Cache);
+ WEBCORE_EXPORT void refreshImportedScripts(ServiceWorkerJobIdentifier, FetchOptions::Cache, Vector<URL>&&, ServiceWorkerJob::RefreshImportedScriptsCallback&&);
WEBCORE_EXPORT void postMessageToServiceWorkerClient(ScriptExecutionContextIdentifier destinationContextIdentifier, MessageWithMessagePorts&&, ServiceWorkerData&& source, String&& sourceOrigin);
WEBCORE_EXPORT void updateRegistrationState(ServiceWorkerRegistrationIdentifier, ServiceWorkerRegistrationState, const std::optional<ServiceWorkerData>&);
WEBCORE_EXPORT void updateWorkerState(ServiceWorkerIdentifier, ServiceWorkerState);
Modified: trunk/Source/WebCore/workers/service/ServiceWorkerContainer.h (293505 => 293506)
--- trunk/Source/WebCore/workers/service/ServiceWorkerContainer.h 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerContainer.h 2022-04-27 13:12:28 UTC (rev 293506)
@@ -129,6 +129,7 @@
void willSettleRegistrationPromise(bool success);
ServiceWorkerOrClientIdentifier contextIdentifier() final;
+ ScriptExecutionContext* context() final { return scriptExecutionContext(); }
SWClientConnection& ensureSWClientConnection();
Modified: trunk/Source/WebCore/workers/service/ServiceWorkerJob.cpp (293505 => 293506)
--- trunk/Source/WebCore/workers/service/ServiceWorkerJob.cpp 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerJob.cpp 2022-04-27 13:12:28 UTC (rev 293506)
@@ -95,27 +95,98 @@
m_client.startScriptFetchForJob(*this, cachePolicy);
}
-void ServiceWorkerJob::fetchScriptWithContext(ScriptExecutionContext& context, FetchOptions::Cache cachePolicy)
+static ResourceRequest scriptResourceRequest(ScriptExecutionContext& context, const URL& url)
{
- ASSERT(m_creationThread.ptr() == &Thread::current());
- ASSERT(!m_completed);
-
- // FIXME: WorkerScriptLoader is the wrong loader class to use here, but there's nothing else better right now.
- m_scriptLoader = WorkerScriptLoader::create();
-
- ResourceRequest request { m_jobData.scriptURL };
+ ResourceRequest request { url };
request.setInitiatorIdentifier(context.resourceRequestIdentifier());
request.addHTTPHeaderField(HTTPHeaderName::ServiceWorker, "script"_s);
+ return request;
+}
+static FetchOptions scriptFetchOptions(FetchOptions::Cache cachePolicy, FetchOptions::Destination destination)
+{
FetchOptions options;
options.mode = FetchOptions::Mode::SameOrigin;
options.cache = cachePolicy;
options.redirect = FetchOptions::Redirect::Error;
- options.destination = FetchOptions::Destination::Serviceworker;
+ options.destination = destination;
options.credentials = FetchOptions::Credentials::SameOrigin;
+ return options;
+}
+ServiceWorkerJob::ImportedScriptsLoader::ImportedScriptsLoader(RefreshImportedScriptsCallback&& callback)
+ : m_callback(WTFMove(callback))
+{
+}
+
+ServiceWorkerJob::ImportedScriptsLoader::~ImportedScriptsLoader()
+{
+ if (m_callback)
+ m_callback({ });
+}
+
+void ServiceWorkerJob::ImportedScriptsLoader::load(ScriptExecutionContext& context, const Vector<URL>& urls, FetchOptions::Cache cachePolicy)
+{
+ m_loaders.reserveCapacity(urls.size());
+ for (auto& url : urls) {
+ auto scriptLoader = WorkerScriptLoader::create();
+ scriptLoader->loadAsynchronously(context, scriptResourceRequest(context, url), WorkerScriptLoader::Source::ClassicWorkerScript, scriptFetchOptions(cachePolicy, FetchOptions::Destination::Script), ContentSecurityPolicyEnforcement::DoNotEnforce, ServiceWorkersMode::None, *this, WorkerRunLoop::defaultMode());
+ if (scriptLoader->failed())
+ continue;
+ m_loaders.uncheckedAppend(WTFMove(scriptLoader));
+ }
+ m_remainingLoads = m_loaders.size();
+}
+
+void ServiceWorkerJob::ImportedScriptsLoader::cancel()
+{
+ auto loaders = WTFMove(m_loaders);
+ for (auto loader : loaders)
+ loader->cancel();
+}
+
+void ServiceWorkerJob::ImportedScriptsLoader::notifyFinished()
+{
+ if (--m_remainingLoads)
+ return;
+
+ Vector<std::pair<URL, ScriptBuffer>> results;
+ results.reserveInitialCapacity(m_loaders.size());
+
+ auto loaders = WTFMove(m_loaders);
+ for (auto loader : loaders) {
+ if (!loader->failed())
+ results.uncheckedAppend(std::make_pair(loader->url(), loader->script()));
+ }
+
+ m_callback(WTFMove(results));
+}
+
+
+void ServiceWorkerJob::refreshImportedScripts(const Vector<URL>& urls, FetchOptions::Cache cachePolicy, RefreshImportedScriptsCallback&& callback)
+{
+ ASSERT(m_creationThread.ptr() == &Thread::current());
+ ASSERT(!m_completed);
+
+ auto* context = m_client.context();
+ if (!context) {
+ callback({ });
+ return;
+ }
+
+ m_importedScriptsLoader = makeUnique<ImportedScriptsLoader>(WTFMove(callback));
+ m_importedScriptsLoader->load(*context, urls, cachePolicy);
+}
+
+void ServiceWorkerJob::fetchScriptWithContext(ScriptExecutionContext& context, FetchOptions::Cache cachePolicy)
+{
+ ASSERT(m_creationThread.ptr() == &Thread::current());
+ ASSERT(!m_completed);
+
auto source = m_jobData.workerType == WorkerType::Module ? WorkerScriptLoader::Source::ModuleScript : WorkerScriptLoader::Source::ClassicWorkerScript;
- m_scriptLoader->loadAsynchronously(context, WTFMove(request), source, WTFMove(options), ContentSecurityPolicyEnforcement::DoNotEnforce, ServiceWorkersMode::None, *this, WorkerRunLoop::defaultMode());
+
+ m_scriptLoader = WorkerScriptLoader::create();
+ m_scriptLoader->loadAsynchronously(context, scriptResourceRequest(context, m_jobData.scriptURL), source, scriptFetchOptions(cachePolicy, FetchOptions::Destination::Serviceworker), ContentSecurityPolicyEnforcement::DoNotEnforce, ServiceWorkersMode::None, *this, WorkerRunLoop::defaultMode());
}
ResourceError ServiceWorkerJob::validateServiceWorkerResponse(const ServiceWorkerJobData& jobData, const ResourceResponse& response)
@@ -180,12 +251,14 @@
bool ServiceWorkerJob::cancelPendingLoad()
{
- if (!m_scriptLoader)
- return false;
+ if (auto importedScriptsLoader = WTFMove(m_importedScriptsLoader))
+ importedScriptsLoader->cancel();
- m_scriptLoader->cancel();
- m_scriptLoader = nullptr;
- return true;
+ if (auto loader = WTFMove(m_scriptLoader)) {
+ m_scriptLoader->cancel();
+ return true;
+ }
+ return false;
}
} // namespace WebCore
Modified: trunk/Source/WebCore/workers/service/ServiceWorkerJob.h (293505 => 293506)
--- trunk/Source/WebCore/workers/service/ServiceWorkerJob.h 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerJob.h 2022-04-27 13:12:28 UTC (rev 293506)
@@ -34,6 +34,7 @@
#include "ServiceWorkerTypes.h"
#include "WorkerScriptLoader.h"
#include "WorkerScriptLoaderClient.h"
+#include <wtf/CompletionHandler.h>
#include <wtf/RefPtr.h>
#include <wtf/RunLoop.h>
#include <wtf/ThreadSafeRefCounted.h>
@@ -58,6 +59,9 @@
void resolvedWithUnregistrationResult(bool);
void startScriptFetch(FetchOptions::Cache);
+ using RefreshImportedScriptsCallback = CompletionHandler<void(Vector<std::pair<URL, ScriptBuffer>>&&)>;
+ void refreshImportedScripts(const Vector<URL>&, FetchOptions::Cache, RefreshImportedScriptsCallback&&);
+
using Identifier = ServiceWorkerJobIdentifier;
Identifier identifier() const { return m_jobData.identifier().jobIdentifier; }
@@ -84,8 +88,26 @@
bool m_completed { false };
+ class ImportedScriptsLoader : public WorkerScriptLoaderClient {
+ WTF_MAKE_FAST_ALLOCATED;
+ public:
+ explicit ImportedScriptsLoader(RefreshImportedScriptsCallback&&);
+ ~ImportedScriptsLoader();
+ void load(ScriptExecutionContext&, const Vector<URL>&, FetchOptions::Cache);
+ void cancel();
+
+ private:
+ void didReceiveResponse(ResourceLoaderIdentifier, const ResourceResponse&) final { }
+ void notifyFinished() final;
+
+ RefreshImportedScriptsCallback m_callback;
+ Vector<Ref<WorkerScriptLoader>> m_loaders;
+ size_t m_remainingLoads { 0 };
+ };
+
ServiceWorkerOrClientIdentifier m_contextIdentifier;
RefPtr<WorkerScriptLoader> m_scriptLoader;
+ std::unique_ptr<ImportedScriptsLoader> m_importedScriptsLoader;
#if ASSERT_ENABLED
Ref<Thread> m_creationThread { Thread::current() };
Modified: trunk/Source/WebCore/workers/service/ServiceWorkerJobClient.h (293505 => 293506)
--- trunk/Source/WebCore/workers/service/ServiceWorkerJobClient.h 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerJobClient.h 2022-04-27 13:12:28 UTC (rev 293506)
@@ -36,6 +36,7 @@
class Exception;
class ResourceError;
class ScriptBuffer;
+class ScriptExecutionContext;
class ServiceWorkerJob;
struct CrossOriginEmbedderPolicy;
struct ServiceWorkerRegistrationData;
@@ -45,6 +46,7 @@
public:
virtual ~ServiceWorkerJobClient() = default;
+ virtual ScriptExecutionContext* context() = 0;
virtual ServiceWorkerOrClientIdentifier contextIdentifier() = 0;
virtual void jobFailedWithException(ServiceWorkerJob&, const Exception&) = 0;
Modified: trunk/Source/WebCore/workers/service/server/SWServer.cpp (293505 => 293506)
--- trunk/Source/WebCore/workers/service/server/SWServer.cpp 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebCore/workers/service/server/SWServer.cpp 2022-04-27 13:12:28 UTC (rev 293506)
@@ -345,9 +345,9 @@
m_registrationStore->flushChanges(WTFMove(completionHandler));
}
-void SWServer::Connection::finishFetchingScriptInServer(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ServiceWorkerRegistrationKey& registrationKey, const WorkerFetchResult& result)
+void SWServer::Connection::finishFetchingScriptInServer(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ServiceWorkerRegistrationKey& registrationKey, WorkerFetchResult&& result)
{
- m_server.scriptFetchFinished(jobDataIdentifier, registrationKey, result);
+ m_server.scriptFetchFinished(jobDataIdentifier, registrationKey, WTFMove(result));
}
void SWServer::Connection::didResolveRegistrationPromise(const ServiceWorkerRegistrationKey& key)
@@ -507,6 +507,27 @@
return url;
}
+ResourceRequest SWServer::createScriptRequest(const URL& url, const ServiceWorkerJobData& jobData, SWServerRegistration& registration)
+{
+ ResourceRequest request { url };
+
+ auto topOrigin = jobData.topOrigin.securityOrigin();
+ auto origin = SecurityOrigin::create(jobData.scriptURL);
+
+ request.setDomainForCachePartition(jobData.domainForCachePartition);
+ request.setAllowCookies(true);
+ request.setFirstPartyForCookies(originURL(topOrigin));
+
+ request.setHTTPHeaderField(HTTPHeaderName::Origin, origin->toString());
+ request.setHTTPHeaderField(HTTPHeaderName::ServiceWorker, "script"_s);
+ request.setHTTPReferrer(originURL(origin).string());
+ request.setHTTPUserAgent(serviceWorkerClientUserAgent(ClientOrigin { jobData.topOrigin, SecurityOrigin::create(jobData.scriptURL)->data() }));
+ request.setPriority(ResourceLoadPriority::Low);
+ request.setIsAppInitiated(registration.isAppInitiated());
+
+ return request;
+}
+
void SWServer::startScriptFetch(const ServiceWorkerJobData& jobData, SWServerRegistration& registration)
{
LOG(ServiceWorker, "Server issuing startScriptFetch for current job %s in client", jobData.identifier().loggingString().utf8().data());
@@ -526,25 +547,9 @@
if (jobData.connectionIdentifier() == Process::identifier()) {
ASSERT(jobData.type == ServiceWorkerJobType::Update);
// This is a soft-update job, create directly a network load to fetch the script.
- ResourceRequest request { jobData.scriptURL };
-
- auto topOrigin = jobData.topOrigin.securityOrigin();
- auto origin = SecurityOrigin::create(jobData.scriptURL);
-
- request.setDomainForCachePartition(jobData.domainForCachePartition);
- request.setAllowCookies(true);
- request.setFirstPartyForCookies(originURL(topOrigin));
-
- request.setHTTPHeaderField(HTTPHeaderName::Origin, origin->toString());
- request.setHTTPHeaderField(HTTPHeaderName::ServiceWorker, "script"_s);
- request.setHTTPReferrer(originURL(origin).string());
- request.setHTTPUserAgent(serviceWorkerClientUserAgent(ClientOrigin { jobData.topOrigin, SecurityOrigin::create(jobData.scriptURL)->data() }));
- request.setPriority(ResourceLoadPriority::Low);
- request.setIsAppInitiated(registration.isAppInitiated());
-
- m_softUpdateCallback(ServiceWorkerJobData { jobData }, shouldRefreshCache, WTFMove(request), [weakThis = WeakPtr { *this }, jobDataIdentifier = jobData.identifier(), registrationKey = jobData.registrationKey()](auto& result) {
+ m_softUpdateCallback(ServiceWorkerJobData { jobData }, shouldRefreshCache, createScriptRequest(jobData.scriptURL, jobData, registration), [weakThis = WeakPtr { *this }, jobDataIdentifier = jobData.identifier(), registrationKey = jobData.registrationKey()](auto&& result) {
if (weakThis)
- weakThis->scriptFetchFinished(jobDataIdentifier, registrationKey, result);
+ weakThis->scriptFetchFinished(jobDataIdentifier, registrationKey, WTFMove(result));
});
return;
}
@@ -551,7 +556,33 @@
ASSERT_WITH_MESSAGE(connection, "If the connection was lost, this job should have been cancelled");
}
-void SWServer::scriptFetchFinished(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ServiceWorkerRegistrationKey& registrationKey, const WorkerFetchResult& result)
+class RefreshImportedScriptsHandler : public RefCounted<RefreshImportedScriptsHandler> {
+public:
+ using Callback = CompletionHandler<void(Vector<std::pair<URL, ScriptBuffer>>&&)>;
+ static Ref<RefreshImportedScriptsHandler> create(size_t expectedItems, Callback&& callback) { return adoptRef(*new RefreshImportedScriptsHandler(expectedItems, WTFMove(callback))); }
+
+ void add(const URL& url, WorkerFetchResult&& result)
+ {
+ if (result.error.isNull())
+ m_scripts.append(std::make_pair(url, WTFMove(result.script)));
+
+ if (!--m_remainingItems)
+ m_callback(std::exchange(m_scripts, { }));
+ }
+
+private:
+ RefreshImportedScriptsHandler(size_t expectedItems, Callback&& callback)
+ : m_remainingItems(expectedItems)
+ , m_callback(WTFMove(callback))
+ {
+ }
+
+ size_t m_remainingItems;
+ Callback m_callback;
+ Vector<std::pair<URL, ScriptBuffer>> m_scripts;
+};
+
+void SWServer::scriptFetchFinished(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ServiceWorkerRegistrationKey& registrationKey, WorkerFetchResult&& result)
{
LOG(ServiceWorker, "Server handling scriptFetchFinished for current job %s in client", jobDataIdentifier.loggingString().utf8().data());
@@ -561,9 +592,41 @@
if (!jobQueue)
return;
- jobQueue->scriptFetchFinished(jobDataIdentifier, result);
+ jobQueue->scriptFetchFinished(jobDataIdentifier, WTFMove(result));
}
+void SWServer::refreshImportedScripts(const ServiceWorkerJobData& jobData, SWServerRegistration& registration, const Vector<URL>& urls)
+{
+ RefreshImportedScriptsHandler::Callback callback = [weakThis = WeakPtr { *this }, jobDataIdentifier = jobData.identifier(), registrationKey = jobData.registrationKey()](auto&& scripts) {
+ if (weakThis)
+ weakThis->refreshImportedScriptsFinished(jobDataIdentifier, registrationKey, scripts);
+ };
+ bool shouldRefreshCache = registration.updateViaCache() == ServiceWorkerUpdateViaCache::None || (registration.getNewestWorker() && registration.isStale());
+
+ auto* connection = m_connections.get(jobData.connectionIdentifier());
+ if (connection) {
+ connection->refreshImportedScripts(jobData.identifier().jobIdentifier, shouldRefreshCache ? FetchOptions::Cache::NoCache : FetchOptions::Cache::Default, urls, WTFMove(callback));
+ return;
+ }
+
+ ASSERT(jobData.connectionIdentifier() == Process::identifier());
+ auto handler = RefreshImportedScriptsHandler::create(urls.size(), WTFMove(callback));
+ for (auto& url : urls) {
+ m_softUpdateCallback(ServiceWorkerJobData { jobData }, shouldRefreshCache, createScriptRequest(url, jobData, registration), [handler, url, size = urls.size()](auto&& result) {
+ handler->add(url, WTFMove(result));
+ });
+ }
+}
+
+void SWServer::refreshImportedScriptsFinished(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ServiceWorkerRegistrationKey& registrationKey, const Vector<std::pair<URL, ScriptBuffer>>& scripts)
+{
+ auto jobQueue = m_jobQueues.get(registrationKey);
+ if (!jobQueue)
+ return;
+
+ jobQueue->importedScriptsFetchFinished(jobDataIdentifier, scripts);
+}
+
void SWServer::scriptContextFailedToStart(const std::optional<ServiceWorkerJobDataIdentifier>& jobDataIdentifier, SWServerWorker& worker, const String& message)
{
if (!jobDataIdentifier)
Modified: trunk/Source/WebCore/workers/service/server/SWServer.h (293505 => 293506)
--- trunk/Source/WebCore/workers/service/server/SWServer.h 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebCore/workers/service/server/SWServer.h 2022-04-27 13:12:28 UTC (rev 293506)
@@ -105,7 +105,7 @@
protected:
WEBCORE_EXPORT Connection(SWServer&, Identifier);
- WEBCORE_EXPORT void finishFetchingScriptInServer(const ServiceWorkerJobDataIdentifier&, const ServiceWorkerRegistrationKey&, const WorkerFetchResult&);
+ WEBCORE_EXPORT void finishFetchingScriptInServer(const ServiceWorkerJobDataIdentifier&, const ServiceWorkerRegistrationKey&, WorkerFetchResult&&);
WEBCORE_EXPORT void addServiceWorkerRegistrationInServer(ServiceWorkerRegistrationIdentifier);
WEBCORE_EXPORT void removeServiceWorkerRegistrationInServer(ServiceWorkerRegistrationIdentifier);
WEBCORE_EXPORT void whenRegistrationReady(const SecurityOriginData& topOrigin, const URL& clientURL, CompletionHandler<void(std::optional<ServiceWorkerRegistrationData>&&)>&&);
@@ -118,6 +118,7 @@
virtual void resolveRegistrationJobInClient(ServiceWorkerJobIdentifier, const ServiceWorkerRegistrationData&, ShouldNotifyWhenResolved) = 0;
virtual void resolveUnregistrationJobInClient(ServiceWorkerJobIdentifier, const ServiceWorkerRegistrationKey&, bool registrationResult) = 0;
virtual void startScriptFetchInClient(ServiceWorkerJobIdentifier, const ServiceWorkerRegistrationKey&, FetchOptions::Cache) = 0;
+ virtual void refreshImportedScripts(ServiceWorkerJobIdentifier, FetchOptions::Cache, const Vector<URL>&, ServiceWorkerJob::RefreshImportedScriptsCallback&&) = 0;
struct RegistrationReadyRequest {
SecurityOriginData topOrigin;
@@ -130,7 +131,7 @@
Vector<RegistrationReadyRequest> m_registrationReadyRequests;
};
- using SoftUpdateCallback = Function<void(ServiceWorkerJobData&& jobData, bool shouldRefreshCache, ResourceRequest&&, CompletionHandler<void(const WorkerFetchResult&)>&&)>;
+ using SoftUpdateCallback = Function<void(ServiceWorkerJobData&& jobData, bool shouldRefreshCache, ResourceRequest&&, CompletionHandler<void(WorkerFetchResult&&)>&&)>;
using CreateContextConnectionCallback = Function<void(const WebCore::RegistrableDomain&, std::optional<ProcessIdentifier> requestingProcessIdentifier, std::optional<ScriptExecutionContextIdentifier>, CompletionHandler<void()>&&)>;
using AppBoundDomainsCallback = Function<void(CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&&)>;
WEBCORE_EXPORT SWServer(UniqueRef<SWOriginStore>&&, bool processTerminationDelayEnabled, String&& registrationDatabaseDirectory, PAL::SessionID, bool shouldRunServiceWorkersOnMainThreadForTesting, bool hasServiceWorkerEntitlement, std::optional<unsigned> overrideServiceWorkerRegistrationCountTestingValue, SoftUpdateCallback&&, CreateContextConnectionCallback&&, AppBoundDomainsCallback&&);
@@ -156,6 +157,7 @@
void resolveRegistrationJob(const ServiceWorkerJobData&, const ServiceWorkerRegistrationData&, ShouldNotifyWhenResolved);
void resolveUnregistrationJob(const ServiceWorkerJobData&, const ServiceWorkerRegistrationKey&, bool unregistrationResult);
void startScriptFetch(const ServiceWorkerJobData&, SWServerRegistration&);
+ void refreshImportedScripts(const ServiceWorkerJobData&, SWServerRegistration&, const Vector<URL>&);
void updateWorker(const ServiceWorkerJobDataIdentifier&, SWServerRegistration&, const URL&, const ScriptBuffer&, const CertificateInfo&, const ContentSecurityPolicyResponseHeaders&, const CrossOriginEmbedderPolicy&, const String& referrerPolicy, WorkerType, MemoryCompactRobinHoodHashMap<URL, ServiceWorkerContextData::ImportedScript>&&, std::optional<ScriptExecutionContextIdentifier> serviceWorkerPageIdentifier);
void fireInstallEvent(SWServerWorker&);
@@ -178,6 +180,7 @@
SWOriginStore& originStore() { return m_originStore; }
+ void refreshImportedScriptsFinished(const ServiceWorkerJobDataIdentifier&, const ServiceWorkerRegistrationKey&, const Vector<std::pair<URL, ScriptBuffer>>&);
void scriptContextFailedToStart(const std::optional<ServiceWorkerJobDataIdentifier>&, SWServerWorker&, const String& message);
void scriptContextStarted(const std::optional<ServiceWorkerJobDataIdentifier>&, SWServerWorker&);
void didFinishInstall(const std::optional<ServiceWorkerJobDataIdentifier>&, SWServerWorker&, bool wasSuccessful);
@@ -259,7 +262,7 @@
bool allowLoopbackIPAddress(const String&);
void validateRegistrationDomain(WebCore::RegistrableDomain, ServiceWorkerJobType, bool, CompletionHandler<void(bool)>&&);
- void scriptFetchFinished(const ServiceWorkerJobDataIdentifier&, const ServiceWorkerRegistrationKey&, const WorkerFetchResult&);
+ void scriptFetchFinished(const ServiceWorkerJobDataIdentifier&, const ServiceWorkerRegistrationKey&, WorkerFetchResult&&);
void didResolveRegistrationPromise(Connection*, const ServiceWorkerRegistrationKey&);
@@ -283,6 +286,8 @@
void updateAppInitiatedValueForWorkers(const ClientOrigin&, LastNavigationWasAppInitiated);
void whenImportIsCompletedIfNeeded(CompletionHandler<void()>&&);
+ ResourceRequest createScriptRequest(const URL&, const ServiceWorkerJobData&, SWServerRegistration&);
+
HashMap<SWServerConnectionIdentifier, std::unique_ptr<Connection>> m_connections;
HashMap<ServiceWorkerRegistrationKey, WeakPtr<SWServerRegistration>> m_scopeToRegistrationMap;
HashMap<ServiceWorkerRegistrationIdentifier, std::unique_ptr<SWServerRegistration>> m_registrations;
Modified: trunk/Source/WebCore/workers/service/server/SWServerJobQueue.cpp (293505 => 293506)
--- trunk/Source/WebCore/workers/service/server/SWServerJobQueue.cpp 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebCore/workers/service/server/SWServerJobQueue.cpp 2022-04-27 13:12:28 UTC (rev 293506)
@@ -69,7 +69,7 @@
#endif
}
-void SWServerJobQueue::scriptFetchFinished(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const WorkerFetchResult& result)
+void SWServerJobQueue::scriptFetchFinished(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, WorkerFetchResult&& result)
{
if (!isCurrentlyProcessingJob(jobDataIdentifier))
return;
@@ -101,20 +101,52 @@
// flag set, and script's source text is a byte-for-byte match with newestWorker's script resource's source
// text, then:
if (newestWorker && equalIgnoringFragmentIdentifier(newestWorker->scriptURL(), job.scriptURL) && newestWorker->type() == job.workerType && result.script == newestWorker->script() && doCertificatesMatch(result.certificateInfo, newestWorker->certificateInfo())) {
- RELEASE_LOG(ServiceWorker, "%p - SWServerJobQueue::scriptFetchFinished, script and certificate are matching for registrationID=%llu", this, registration->identifier().toUInt64());
+
+ auto scriptURLs = newestWorker->importedScriptURLs();
+ if (!scriptURLs.isEmpty()) {
+ m_workerFetchResult = WTFMove(result);
+ m_server.refreshImportedScripts(job, *registration, scriptURLs);
+ return;
+ }
+
// FIXME: for non classic scripts, check the script’s module record's [[ECMAScriptCode]].
- // Invoke Resolve Job Promise with job and registration.
- m_server.resolveRegistrationJob(job, registration->data(), ShouldNotifyWhenResolved::No);
+ RELEASE_LOG(ServiceWorker, "%p - SWServerJobQueue::scriptFetchFinished, script, certificate and imported scripts are matching for registrationID=%llu", this, registration->identifier().toUInt64());
+ scriptAndImportedScriptsFetchFinished(job, *registration);
+ return;
+ }
- // Invoke Finish Job with job and abort these steps.
- finishCurrentJob();
+ m_server.updateWorker(job.identifier(), *registration, job.scriptURL, result.script, result.certificateInfo, result.contentSecurityPolicy, result.crossOriginEmbedderPolicy, result.referrerPolicy, job.workerType, { }, job.serviceWorkerPageIdentifier());
+}
+
+void SWServerJobQueue::importedScriptsFetchFinished(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const Vector<std::pair<URL, ScriptBuffer>>& importedScripts)
+{
+ if (!isCurrentlyProcessingJob(jobDataIdentifier))
return;
+
+ auto& job = firstJob();
+
+ auto* registration = m_server.getRegistration(m_registrationKey);
+ if (!registration)
+ return;
+
+ auto* newestWorker = registration->getNewestWorker();
+ if (newestWorker && newestWorker->matchingImportedScripts(importedScripts)) {
+ RELEASE_LOG(ServiceWorker, "%p - SWServerJobQueue::importedScriptsFetchFinished, script, certificate and imported scripts are matching for registrationID=%llu", this, registration->identifier().toUInt64());
+ scriptAndImportedScriptsFetchFinished(job, *registration);
+ return;
}
- // FIXME: Update all the imported scripts as per spec. For now, we just do as if there is none.
+ m_server.updateWorker(job.identifier(), *registration, job.scriptURL, m_workerFetchResult.script, m_workerFetchResult.certificateInfo, m_workerFetchResult.contentSecurityPolicy, m_workerFetchResult.crossOriginEmbedderPolicy, m_workerFetchResult.referrerPolicy, job.workerType, { }, job.serviceWorkerPageIdentifier());
+}
- m_server.updateWorker(job.identifier(), *registration, job.scriptURL, result.script, result.certificateInfo, result.contentSecurityPolicy, result.crossOriginEmbedderPolicy, result.referrerPolicy, job.workerType, { }, job.serviceWorkerPageIdentifier());
+void SWServerJobQueue::scriptAndImportedScriptsFetchFinished(const ServiceWorkerJobData& job, SWServerRegistration& registration)
+{
+ // Invoke Resolve Job Promise with job and registration.
+ m_server.resolveRegistrationJob(job, registration.data(), ShouldNotifyWhenResolved::No);
+
+ // Invoke Finish Job with job and abort these steps.
+ finishCurrentJob();
}
// https://w3c.github.io/ServiceWorker/#update-algorithm
Modified: trunk/Source/WebCore/workers/service/server/SWServerJobQueue.h (293505 => 293506)
--- trunk/Source/WebCore/workers/service/server/SWServerJobQueue.h 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebCore/workers/service/server/SWServerJobQueue.h 2022-04-27 13:12:28 UTC (rev 293506)
@@ -30,11 +30,13 @@
#include "SWServer.h"
#include "ServiceWorkerJobData.h"
#include "Timer.h"
+#include "WorkerFetchResult.h"
#include <wtf/Deque.h>
namespace WebCore {
class SWServerWorker;
+class ServiceWorkerJob;
struct WorkerFetchResult;
class SWServerJobQueue {
@@ -51,7 +53,8 @@
void runNextJob();
- void scriptFetchFinished(const ServiceWorkerJobDataIdentifier&, const WorkerFetchResult&);
+ void scriptFetchFinished(const ServiceWorkerJobDataIdentifier&, WorkerFetchResult&&);
+ void importedScriptsFetchFinished(const ServiceWorkerJobDataIdentifier&, const Vector<std::pair<URL, ScriptBuffer>>&);
void scriptContextFailedToStart(const ServiceWorkerJobDataIdentifier&, ServiceWorkerIdentifier, const String& message);
void scriptContextStarted(const ServiceWorkerJobDataIdentifier&, ServiceWorkerIdentifier);
void didFinishInstall(const ServiceWorkerJobDataIdentifier&, SWServerWorker&, bool wasSuccessful);
@@ -74,6 +77,7 @@
void install(SWServerRegistration&, ServiceWorkerIdentifier);
void removeAllJobsMatching(const Function<bool(ServiceWorkerJobData&)>&);
+ void scriptAndImportedScriptsFetchFinished(const ServiceWorkerJobData&, SWServerRegistration&);
Deque<ServiceWorkerJobData> m_jobQueue;
@@ -80,6 +84,7 @@
Timer m_jobTimer;
SWServer& m_server;
ServiceWorkerRegistrationKey m_registrationKey;
+ WorkerFetchResult m_workerFetchResult;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/workers/service/server/SWServerWorker.cpp (293505 => 293506)
--- trunk/Source/WebCore/workers/service/server/SWServerWorker.cpp 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebCore/workers/service/server/SWServerWorker.cpp 2022-04-27 13:12:28 UTC (rev 293506)
@@ -427,6 +427,21 @@
return registrationIdentifier == m_data.registrationIdentifier;
}
+Vector<URL> SWServerWorker::importedScriptURLs() const
+{
+ return copyToVector(m_scriptResourceMap.keys());
+}
+
+bool SWServerWorker::matchingImportedScripts(const Vector<std::pair<URL, ScriptBuffer>>& scripts) const
+{
+ for (auto& script : scripts) {
+ auto iterator = m_scriptResourceMap.find(script.first);
+ if (iterator == m_scriptResourceMap.end() || iterator->value.script != script.second)
+ return false;
+ }
+ return true;
+}
+
} // namespace WebCore
#endif // ENABLE(SERVICE_WORKER)
Modified: trunk/Source/WebCore/workers/service/server/SWServerWorker.h (293505 => 293506)
--- trunk/Source/WebCore/workers/service/server/SWServerWorker.h 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebCore/workers/service/server/SWServerWorker.h 2022-04-27 13:12:28 UTC (rev 293506)
@@ -144,6 +144,10 @@
WEBCORE_EXPORT bool isClientActiveServiceWorker(ScriptExecutionContextIdentifier) const;
+ Vector<URL> importedScriptURLs() const;
+ const MemoryCompactRobinHoodHashMap<URL, ServiceWorkerContextData::ImportedScript>& scriptResourceMap() const { return m_scriptResourceMap; }
+ bool matchingImportedScripts(const Vector<std::pair<URL, ScriptBuffer>>&) const;
+
private:
SWServerWorker(SWServer&, SWServerRegistration&, const URL&, const ScriptBuffer&, const CertificateInfo&, const ContentSecurityPolicyResponseHeaders&, const CrossOriginEmbedderPolicy&, String&& referrerPolicy, WorkerType, ServiceWorkerIdentifier, MemoryCompactRobinHoodHashMap<URL, ServiceWorkerContextData::ImportedScript>&&);
Modified: trunk/Source/WebKit/ChangeLog (293505 => 293506)
--- trunk/Source/WebKit/ChangeLog 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebKit/ChangeLog 2022-04-27 13:12:28 UTC (rev 293506)
@@ -1,5 +1,17 @@
2022-04-27 Youenn Fablet <[email protected]>
+ service worker update should refresh imported scripts in addition to the main script
+ https://bugs.webkit.org/show_bug.cgi?id=239657
+
+ Reviewed by Chris Dumez.
+
+ * NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.h:
+ * NetworkProcess/ServiceWorker/WebSWServerConnection.cpp:
+ * NetworkProcess/ServiceWorker/WebSWServerConnection.h:
+ * WebProcess/Storage/WebSWClientConnection.messages.in:
+
+2022-04-27 Youenn Fablet <[email protected]>
+
Add testRunner API to clear memory cache
https://bugs.webkit.org/show_bug.cgi?id=239804
rdar://92033309
Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.h (293505 => 293506)
--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.h 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.h 2022-04-27 13:12:28 UTC (rev 293506)
@@ -50,7 +50,7 @@
class ServiceWorkerSoftUpdateLoader final : public NetworkLoadClient, public CanMakeWeakPtr<ServiceWorkerSoftUpdateLoader> {
WTF_MAKE_FAST_ALLOCATED;
public:
- using Handler = CompletionHandler<void(const WebCore::WorkerFetchResult&)>;
+ using Handler = CompletionHandler<void(WebCore::WorkerFetchResult&&)>;
static void start(NetworkSession*, WebCore::ServiceWorkerJobData&&, bool shouldRefreshCache, WebCore::ResourceRequest&&, Handler&&);
~ServiceWorkerSoftUpdateLoader();
Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp (293505 => 293506)
--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp 2022-04-27 13:12:28 UTC (rev 293506)
@@ -134,6 +134,11 @@
send(Messages::WebSWClientConnection::StartScriptFetchForServer(jobIdentifier, registrationKey, cachePolicy));
}
+void WebSWServerConnection::refreshImportedScripts(ServiceWorkerJobIdentifier jobIdentifier, FetchOptions::Cache cachePolicy, const Vector<URL>& urls, ServiceWorkerJob::RefreshImportedScriptsCallback&& callback)
+{
+ sendWithAsyncReply(Messages::WebSWClientConnection::RefreshImportedScripts(jobIdentifier, cachePolicy, urls), WTFMove(callback));
+}
+
void WebSWServerConnection::updateRegistrationStateInClient(ServiceWorkerRegistrationIdentifier identifier, ServiceWorkerRegistrationState state, const std::optional<ServiceWorkerData>& serviceWorkerData)
{
send(Messages::WebSWClientConnection::UpdateRegistrationState(identifier, state, serviceWorkerData));
Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.h (293505 => 293506)
--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.h 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.h 2022-04-27 13:12:28 UTC (rev 293506)
@@ -96,6 +96,7 @@
void resolveRegistrationJobInClient(WebCore::ServiceWorkerJobIdentifier, const WebCore::ServiceWorkerRegistrationData&, WebCore::ShouldNotifyWhenResolved) final;
void resolveUnregistrationJobInClient(WebCore::ServiceWorkerJobIdentifier, const WebCore::ServiceWorkerRegistrationKey&, bool unregistrationResult) final;
void startScriptFetchInClient(WebCore::ServiceWorkerJobIdentifier, const WebCore::ServiceWorkerRegistrationKey&, WebCore::FetchOptions::Cache) final;
+ void refreshImportedScripts(WebCore::ServiceWorkerJobIdentifier, WebCore::FetchOptions::Cache, const Vector<URL>&, WebCore::ServiceWorkerJob::RefreshImportedScriptsCallback&&);
void updateRegistrationStateInClient(WebCore::ServiceWorkerRegistrationIdentifier, WebCore::ServiceWorkerRegistrationState, const std::optional<WebCore::ServiceWorkerData>&) final;
void updateWorkerStateInClient(WebCore::ServiceWorkerIdentifier, WebCore::ServiceWorkerState) final;
void fireUpdateFoundEvent(WebCore::ServiceWorkerRegistrationIdentifier) final;
Modified: trunk/Source/WebKit/WebProcess/Storage/WebSWClientConnection.messages.in (293505 => 293506)
--- trunk/Source/WebKit/WebProcess/Storage/WebSWClientConnection.messages.in 2022-04-27 11:59:59 UTC (rev 293505)
+++ trunk/Source/WebKit/WebProcess/Storage/WebSWClientConnection.messages.in 2022-04-27 13:12:28 UTC (rev 293506)
@@ -27,6 +27,7 @@
JobRejectedInServer(WebCore::ServiceWorkerJobIdentifier jobDataIdentifier, struct WebCore::ExceptionData exception)
RegistrationJobResolvedInServer(WebCore::ServiceWorkerJobIdentifier jobDataIdentifier, struct WebCore::ServiceWorkerRegistrationData registration, enum:bool WebCore::ShouldNotifyWhenResolved shouldNotifyWhenResolved)
StartScriptFetchForServer(WebCore::ServiceWorkerJobIdentifier jobDataIdentifier, WebCore::ServiceWorkerRegistrationKey registrationKey, WebCore::FetchOptions::Cache cachePolicy)
+ RefreshImportedScripts(WebCore::ServiceWorkerJobIdentifier jobDataIdentifier, WebCore::FetchOptions::Cache cachePolicy, Vector<URL> urls) -> (Vector<std::pair<URL, WebCore::ScriptBuffer>> results);
UpdateRegistrationState(WebCore::ServiceWorkerRegistrationIdentifier identifier, enum:uint8_t WebCore::ServiceWorkerRegistrationState state, std::optional<WebCore::ServiceWorkerData> serviceWorkerIdentifier)
UpdateWorkerState(WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, enum:uint8_t WebCore::ServiceWorkerState state)
FireUpdateFoundEvent(WebCore::ServiceWorkerRegistrationIdentifier identifier)