Changeset 293506 in webkit


Ignore:
Timestamp:
Apr 27, 2022 6:12:28 AM (3 months ago)
Author:
youenn@apple.com
Message:

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.

LayoutTests/imported/w3c:

  • web-platform-tests/service-workers/service-worker/credentials.https-expected.txt:

Source/WebCore:

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:

Source/WebKit:

  • NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.h:
  • NetworkProcess/ServiceWorker/WebSWServerConnection.cpp:
  • NetworkProcess/ServiceWorker/WebSWServerConnection.h:
  • WebProcess/Storage/WebSWClientConnection.messages.in:
Location:
trunk
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r293501 r293506  
     12022-04-27  Youenn Fablet  <youenn@apple.com>
     2
     3        service worker update should refresh imported scripts in addition to the main script
     4        https://bugs.webkit.org/show_bug.cgi?id=239657
     5
     6        Reviewed by Chris Dumez.
     7
     8        * web-platform-tests/service-workers/service-worker/credentials.https-expected.txt:
     9
    1102022-04-27  Youenn Fablet  <youenn@apple.com>
    211
  • trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/credentials.https-expected.txt

    r279389 r293506  
    22PASS Set cookies as initialization
    33PASS Main script should have credentials
    4 FAIL Imported script should have credentials promise_test: Unhandled rejection with value: object "TypeError: null is not an object (evaluating 'worker.postMessage')"
    5 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')"
     4PASS Imported script should have credentials
     5PASS Module with an imported statement should not have credentials
    66FAIL 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"
    77
  • trunk/Source/WebCore/ChangeLog

    r293504 r293506  
     12022-04-27  Youenn Fablet  <youenn@apple.com>
     2
     3        service worker update should refresh imported scripts in addition to the main script
     4        https://bugs.webkit.org/show_bug.cgi?id=239657
     5
     6        Reviewed by Chris Dumez.
     7
     8        After checking main script, if matching, we refreach each identified imported script.
     9        If matching, we reuse the same worker, otherwise we install a new one.
     10        We reuse the soft update loader to fetch scripts in case of soft update.
     11        Otherwise, we load scripts through the job's client.
     12
     13        Covered by rebased test.
     14
     15        * workers/service/SWClientConnection.cpp:
     16        * workers/service/SWClientConnection.h:
     17        * workers/service/ServiceWorkerContainer.cpp:
     18        * workers/service/ServiceWorkerContainer.h:
     19        * workers/service/ServiceWorkerJob.cpp:
     20        * workers/service/ServiceWorkerJob.h:
     21        * workers/service/ServiceWorkerJobClient.h:
     22        * workers/service/server/SWServer.cpp:
     23        * workers/service/server/SWServer.h:
     24        * workers/service/server/SWServerJobQueue.cpp:
     25        * workers/service/server/SWServerJobQueue.h:
     26        * workers/service/server/SWServerWorker.cpp:
     27        * workers/service/server/SWServerWorker.h:
     28
    1292022-04-27  Nikolas Zimmermann  <nzimmermann@igalia.com>
    230
  • trunk/Source/WebCore/workers/service/SWClientConnection.cpp

    r293501 r293506  
    116116}
    117117
     118class RefreshImportedScriptsCallbackHandler {
     119    WTF_MAKE_FAST_ALLOCATED;
     120public:
     121    explicit RefreshImportedScriptsCallbackHandler(ServiceWorkerJob::RefreshImportedScriptsCallback&& callback)
     122        : m_callback(WTFMove(callback))
     123    {
     124    }
     125
     126    ~RefreshImportedScriptsCallbackHandler()
     127    {
     128        if (!m_callback)
     129            return;
     130
     131        callOnMainThread([callback = WTFMove(m_callback)] () mutable {
     132            callback({ });
     133        });
     134    }
     135
     136    void call(Vector<std::pair<URL, ScriptBuffer>>&& scripts)
     137    {
     138        callOnMainThread([callback = WTFMove(m_callback), scripts = crossThreadCopy(WTFMove(scripts))] () mutable {
     139            callback(WTFMove(scripts));
     140        });
     141    }
     142
     143private:
     144    ServiceWorkerJob::RefreshImportedScriptsCallback m_callback;
     145};
     146
     147void SWClientConnection::refreshImportedScripts(ServiceWorkerJobIdentifier jobIdentifier, FetchOptions::Cache cachePolicy, Vector<URL>&& urls, ServiceWorkerJob::RefreshImportedScriptsCallback&& callback)
     148{
     149    ASSERT(isMainThread());
     150    auto handler = makeUnique<RefreshImportedScriptsCallbackHandler>(WTFMove(callback));
     151    postTaskForJob(jobIdentifier, IsJobComplete::No, [cachePolicy, urls = crossThreadCopy(WTFMove(urls)), handler = WTFMove(handler)] (auto& job) mutable {
     152        job.refreshImportedScripts(urls, cachePolicy, [handler = WTFMove(handler)] (auto&& result) {
     153            handler->call(WTFMove(result));
     154        });
     155    });
     156}
    118157
    119158static void postMessageToContainer(ScriptExecutionContext& context, MessageWithMessagePorts&& message, ServiceWorkerData&& sourceData, String&& sourceOrigin)
  • trunk/Source/WebCore/workers/service/SWClientConnection.h

    r292905 r293506  
    125125    WEBCORE_EXPORT void registrationJobResolvedInServer(ServiceWorkerJobIdentifier, ServiceWorkerRegistrationData&&, ShouldNotifyWhenResolved);
    126126    WEBCORE_EXPORT void startScriptFetchForServer(ServiceWorkerJobIdentifier, ServiceWorkerRegistrationKey&&, FetchOptions::Cache);
     127    WEBCORE_EXPORT void refreshImportedScripts(ServiceWorkerJobIdentifier, FetchOptions::Cache, Vector<URL>&&, ServiceWorkerJob::RefreshImportedScriptsCallback&&);
    127128    WEBCORE_EXPORT void postMessageToServiceWorkerClient(ScriptExecutionContextIdentifier destinationContextIdentifier, MessageWithMessagePorts&&, ServiceWorkerData&& source, String&& sourceOrigin);
    128129    WEBCORE_EXPORT void updateRegistrationState(ServiceWorkerRegistrationIdentifier, ServiceWorkerRegistrationState, const std::optional<ServiceWorkerData>&);
  • trunk/Source/WebCore/workers/service/ServiceWorkerContainer.h

    r292218 r293506  
    130130
    131131    ServiceWorkerOrClientIdentifier contextIdentifier() final;
     132    ScriptExecutionContext* context() final { return scriptExecutionContext(); }
    132133
    133134    SWClientConnection& ensureSWClientConnection();
  • trunk/Source/WebCore/workers/service/ServiceWorkerJob.cpp

    r292857 r293506  
    9696}
    9797
    98 void ServiceWorkerJob::fetchScriptWithContext(ScriptExecutionContext& context, FetchOptions::Cache cachePolicy)
    99 {
    100     ASSERT(m_creationThread.ptr() == &Thread::current());
    101     ASSERT(!m_completed);
    102 
    103     // FIXME: WorkerScriptLoader is the wrong loader class to use here, but there's nothing else better right now.
    104     m_scriptLoader = WorkerScriptLoader::create();
    105 
    106     ResourceRequest request { m_jobData.scriptURL };
     98static ResourceRequest scriptResourceRequest(ScriptExecutionContext& context, const URL& url)
     99{
     100    ResourceRequest request { url };
    107101    request.setInitiatorIdentifier(context.resourceRequestIdentifier());
    108102    request.addHTTPHeaderField(HTTPHeaderName::ServiceWorker, "script"_s);
    109 
     103    return request;
     104}
     105
     106static FetchOptions scriptFetchOptions(FetchOptions::Cache cachePolicy, FetchOptions::Destination destination)
     107{
    110108    FetchOptions options;
    111109    options.mode = FetchOptions::Mode::SameOrigin;
    112110    options.cache = cachePolicy;
    113111    options.redirect = FetchOptions::Redirect::Error;
    114     options.destination = FetchOptions::Destination::Serviceworker;
     112    options.destination = destination;
    115113    options.credentials = FetchOptions::Credentials::SameOrigin;
     114    return options;
     115}
     116
     117ServiceWorkerJob::ImportedScriptsLoader::ImportedScriptsLoader(RefreshImportedScriptsCallback&& callback)
     118    : m_callback(WTFMove(callback))
     119{
     120}
     121
     122ServiceWorkerJob::ImportedScriptsLoader::~ImportedScriptsLoader()
     123{
     124    if (m_callback)
     125        m_callback({ });
     126}
     127
     128void ServiceWorkerJob::ImportedScriptsLoader::load(ScriptExecutionContext& context, const Vector<URL>& urls, FetchOptions::Cache cachePolicy)
     129{
     130    m_loaders.reserveCapacity(urls.size());
     131    for (auto& url : urls) {
     132        auto scriptLoader = WorkerScriptLoader::create();
     133        scriptLoader->loadAsynchronously(context, scriptResourceRequest(context, url), WorkerScriptLoader::Source::ClassicWorkerScript, scriptFetchOptions(cachePolicy, FetchOptions::Destination::Script), ContentSecurityPolicyEnforcement::DoNotEnforce, ServiceWorkersMode::None, *this, WorkerRunLoop::defaultMode());
     134        if (scriptLoader->failed())
     135            continue;
     136        m_loaders.uncheckedAppend(WTFMove(scriptLoader));
     137    }
     138    m_remainingLoads = m_loaders.size();
     139}
     140
     141void ServiceWorkerJob::ImportedScriptsLoader::cancel()
     142{
     143    auto loaders = WTFMove(m_loaders);
     144    for (auto loader : loaders)
     145        loader->cancel();
     146}
     147
     148void ServiceWorkerJob::ImportedScriptsLoader::notifyFinished()
     149{
     150    if (--m_remainingLoads)
     151        return;
     152
     153    Vector<std::pair<URL, ScriptBuffer>> results;
     154    results.reserveInitialCapacity(m_loaders.size());
     155
     156    auto loaders = WTFMove(m_loaders);
     157    for (auto loader : loaders) {
     158        if (!loader->failed())
     159            results.uncheckedAppend(std::make_pair(loader->url(), loader->script()));
     160    }
     161
     162    m_callback(WTFMove(results));
     163}
     164
     165
     166void ServiceWorkerJob::refreshImportedScripts(const Vector<URL>& urls, FetchOptions::Cache cachePolicy, RefreshImportedScriptsCallback&& callback)
     167{
     168    ASSERT(m_creationThread.ptr() == &Thread::current());
     169    ASSERT(!m_completed);
     170
     171    auto* context = m_client.context();
     172    if (!context) {
     173        callback({ });
     174        return;
     175    }
     176
     177    m_importedScriptsLoader = makeUnique<ImportedScriptsLoader>(WTFMove(callback));
     178    m_importedScriptsLoader->load(*context, urls, cachePolicy);
     179}
     180
     181void ServiceWorkerJob::fetchScriptWithContext(ScriptExecutionContext& context, FetchOptions::Cache cachePolicy)
     182{
     183    ASSERT(m_creationThread.ptr() == &Thread::current());
     184    ASSERT(!m_completed);
    116185
    117186    auto source = m_jobData.workerType == WorkerType::Module ? WorkerScriptLoader::Source::ModuleScript : WorkerScriptLoader::Source::ClassicWorkerScript;
    118     m_scriptLoader->loadAsynchronously(context, WTFMove(request), source, WTFMove(options), ContentSecurityPolicyEnforcement::DoNotEnforce, ServiceWorkersMode::None, *this, WorkerRunLoop::defaultMode());
     187
     188    m_scriptLoader = WorkerScriptLoader::create();
     189    m_scriptLoader->loadAsynchronously(context, scriptResourceRequest(context, m_jobData.scriptURL), source, scriptFetchOptions(cachePolicy, FetchOptions::Destination::Serviceworker), ContentSecurityPolicyEnforcement::DoNotEnforce, ServiceWorkersMode::None, *this, WorkerRunLoop::defaultMode());
    119190}
    120191
     
    181252bool ServiceWorkerJob::cancelPendingLoad()
    182253{
    183     if (!m_scriptLoader)
    184         return false;
    185 
    186     m_scriptLoader->cancel();
    187     m_scriptLoader = nullptr;
    188     return true;
     254    if (auto importedScriptsLoader = WTFMove(m_importedScriptsLoader))
     255        importedScriptsLoader->cancel();
     256
     257    if (auto loader = WTFMove(m_scriptLoader)) {
     258        m_scriptLoader->cancel();
     259        return true;
     260    }
     261    return false;
    189262}
    190263
  • trunk/Source/WebCore/workers/service/ServiceWorkerJob.h

    r286012 r293506  
    3535#include "WorkerScriptLoader.h"
    3636#include "WorkerScriptLoaderClient.h"
     37#include <wtf/CompletionHandler.h>
    3738#include <wtf/RefPtr.h>
    3839#include <wtf/RunLoop.h>
     
    5859    void resolvedWithUnregistrationResult(bool);
    5960    void startScriptFetch(FetchOptions::Cache);
     61
     62    using RefreshImportedScriptsCallback = CompletionHandler<void(Vector<std::pair<URL, ScriptBuffer>>&&)>;
     63    void refreshImportedScripts(const Vector<URL>&, FetchOptions::Cache, RefreshImportedScriptsCallback&&);
    6064
    6165    using Identifier = ServiceWorkerJobIdentifier;
     
    8589    bool m_completed { false };
    8690
     91    class ImportedScriptsLoader : public WorkerScriptLoaderClient {
     92        WTF_MAKE_FAST_ALLOCATED;
     93    public:
     94        explicit ImportedScriptsLoader(RefreshImportedScriptsCallback&&);
     95        ~ImportedScriptsLoader();
     96        void load(ScriptExecutionContext&, const Vector<URL>&, FetchOptions::Cache);
     97        void cancel();
     98
     99    private:
     100        void didReceiveResponse(ResourceLoaderIdentifier, const ResourceResponse&) final { }
     101        void notifyFinished() final;
     102
     103        RefreshImportedScriptsCallback m_callback;
     104        Vector<Ref<WorkerScriptLoader>> m_loaders;
     105        size_t m_remainingLoads { 0 };
     106    };
     107
    87108    ServiceWorkerOrClientIdentifier m_contextIdentifier;
    88109    RefPtr<WorkerScriptLoader> m_scriptLoader;
     110    std::unique_ptr<ImportedScriptsLoader> m_importedScriptsLoader;
    89111
    90112#if ASSERT_ENABLED
  • trunk/Source/WebCore/workers/service/ServiceWorkerJobClient.h

    r291003 r293506  
    3737class ResourceError;
    3838class ScriptBuffer;
     39class ScriptExecutionContext;
    3940class ServiceWorkerJob;
    4041struct CrossOriginEmbedderPolicy;
     
    4647    virtual ~ServiceWorkerJobClient() = default;
    4748
     49    virtual ScriptExecutionContext* context() = 0;
    4850    virtual ServiceWorkerOrClientIdentifier contextIdentifier() = 0;
    4951
  • trunk/Source/WebCore/workers/service/server/SWServer.cpp

    r293501 r293506  
    346346}
    347347
    348 void SWServer::Connection::finishFetchingScriptInServer(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ServiceWorkerRegistrationKey& registrationKey, const WorkerFetchResult& result)
    349 {
    350     m_server.scriptFetchFinished(jobDataIdentifier, registrationKey, result);
     348void SWServer::Connection::finishFetchingScriptInServer(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ServiceWorkerRegistrationKey& registrationKey, WorkerFetchResult&& result)
     349{
     350    m_server.scriptFetchFinished(jobDataIdentifier, registrationKey, WTFMove(result));
    351351}
    352352
     
    508508}
    509509
     510ResourceRequest SWServer::createScriptRequest(const URL& url, const ServiceWorkerJobData& jobData, SWServerRegistration& registration)
     511{
     512    ResourceRequest request { url };
     513
     514    auto topOrigin = jobData.topOrigin.securityOrigin();
     515    auto origin = SecurityOrigin::create(jobData.scriptURL);
     516
     517    request.setDomainForCachePartition(jobData.domainForCachePartition);
     518    request.setAllowCookies(true);
     519    request.setFirstPartyForCookies(originURL(topOrigin));
     520
     521    request.setHTTPHeaderField(HTTPHeaderName::Origin, origin->toString());
     522    request.setHTTPHeaderField(HTTPHeaderName::ServiceWorker, "script"_s);
     523    request.setHTTPReferrer(originURL(origin).string());
     524    request.setHTTPUserAgent(serviceWorkerClientUserAgent(ClientOrigin { jobData.topOrigin, SecurityOrigin::create(jobData.scriptURL)->data() }));
     525    request.setPriority(ResourceLoadPriority::Low);
     526    request.setIsAppInitiated(registration.isAppInitiated());
     527
     528    return request;
     529}
     530
    510531void SWServer::startScriptFetch(const ServiceWorkerJobData& jobData, SWServerRegistration& registration)
    511532{
     
    527548        ASSERT(jobData.type == ServiceWorkerJobType::Update);
    528549        // This is a soft-update job, create directly a network load to fetch the script.
    529         ResourceRequest request { jobData.scriptURL };
    530 
    531         auto topOrigin = jobData.topOrigin.securityOrigin();
    532         auto origin = SecurityOrigin::create(jobData.scriptURL);
    533 
    534         request.setDomainForCachePartition(jobData.domainForCachePartition);
    535         request.setAllowCookies(true);
    536         request.setFirstPartyForCookies(originURL(topOrigin));
    537 
    538         request.setHTTPHeaderField(HTTPHeaderName::Origin, origin->toString());
    539         request.setHTTPHeaderField(HTTPHeaderName::ServiceWorker, "script"_s);
    540         request.setHTTPReferrer(originURL(origin).string());
    541         request.setHTTPUserAgent(serviceWorkerClientUserAgent(ClientOrigin { jobData.topOrigin, SecurityOrigin::create(jobData.scriptURL)->data() }));
    542         request.setPriority(ResourceLoadPriority::Low);
    543         request.setIsAppInitiated(registration.isAppInitiated());
    544 
    545         m_softUpdateCallback(ServiceWorkerJobData { jobData }, shouldRefreshCache, WTFMove(request), [weakThis = WeakPtr { *this }, jobDataIdentifier = jobData.identifier(), registrationKey = jobData.registrationKey()](auto& result) {
     550        m_softUpdateCallback(ServiceWorkerJobData { jobData }, shouldRefreshCache, createScriptRequest(jobData.scriptURL, jobData, registration), [weakThis = WeakPtr { *this }, jobDataIdentifier = jobData.identifier(), registrationKey = jobData.registrationKey()](auto&& result) {
    546551            if (weakThis)
    547                 weakThis->scriptFetchFinished(jobDataIdentifier, registrationKey, result);
     552                weakThis->scriptFetchFinished(jobDataIdentifier, registrationKey, WTFMove(result));
    548553        });
    549554        return;
     
    552557}
    553558
    554 void SWServer::scriptFetchFinished(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ServiceWorkerRegistrationKey& registrationKey, const WorkerFetchResult& result)
     559class RefreshImportedScriptsHandler : public RefCounted<RefreshImportedScriptsHandler> {
     560public:
     561    using Callback = CompletionHandler<void(Vector<std::pair<URL, ScriptBuffer>>&&)>;
     562    static Ref<RefreshImportedScriptsHandler> create(size_t expectedItems, Callback&& callback) { return adoptRef(*new RefreshImportedScriptsHandler(expectedItems, WTFMove(callback))); }
     563
     564    void add(const URL& url, WorkerFetchResult&& result)
     565    {
     566        if (result.error.isNull())
     567            m_scripts.append(std::make_pair(url, WTFMove(result.script)));
     568
     569        if (!--m_remainingItems)
     570            m_callback(std::exchange(m_scripts, { }));
     571    }
     572
     573private:
     574    RefreshImportedScriptsHandler(size_t expectedItems, Callback&& callback)
     575        : m_remainingItems(expectedItems)
     576        , m_callback(WTFMove(callback))
     577    {
     578    }
     579
     580    size_t m_remainingItems;
     581    Callback m_callback;
     582    Vector<std::pair<URL, ScriptBuffer>> m_scripts;
     583};
     584
     585void SWServer::scriptFetchFinished(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ServiceWorkerRegistrationKey& registrationKey, WorkerFetchResult&& result)
    555586{
    556587    LOG(ServiceWorker, "Server handling scriptFetchFinished for current job %s in client", jobDataIdentifier.loggingString().utf8().data());
     
    562593        return;
    563594
    564     jobQueue->scriptFetchFinished(jobDataIdentifier, result);
     595    jobQueue->scriptFetchFinished(jobDataIdentifier, WTFMove(result));
     596}
     597
     598void SWServer::refreshImportedScripts(const ServiceWorkerJobData& jobData, SWServerRegistration& registration, const Vector<URL>& urls)
     599{
     600    RefreshImportedScriptsHandler::Callback callback = [weakThis = WeakPtr { *this }, jobDataIdentifier = jobData.identifier(), registrationKey = jobData.registrationKey()](auto&& scripts) {
     601        if (weakThis)
     602            weakThis->refreshImportedScriptsFinished(jobDataIdentifier, registrationKey, scripts);
     603    };
     604    bool shouldRefreshCache = registration.updateViaCache() == ServiceWorkerUpdateViaCache::None || (registration.getNewestWorker() && registration.isStale());
     605
     606    auto* connection = m_connections.get(jobData.connectionIdentifier());
     607    if (connection) {
     608        connection->refreshImportedScripts(jobData.identifier().jobIdentifier, shouldRefreshCache ? FetchOptions::Cache::NoCache : FetchOptions::Cache::Default, urls, WTFMove(callback));
     609        return;
     610    }
     611
     612    ASSERT(jobData.connectionIdentifier() == Process::identifier());
     613    auto handler = RefreshImportedScriptsHandler::create(urls.size(), WTFMove(callback));
     614    for (auto& url : urls) {
     615        m_softUpdateCallback(ServiceWorkerJobData { jobData }, shouldRefreshCache, createScriptRequest(url, jobData, registration), [handler, url, size = urls.size()](auto&& result) {
     616            handler->add(url, WTFMove(result));
     617        });
     618    }
     619}
     620
     621void SWServer::refreshImportedScriptsFinished(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ServiceWorkerRegistrationKey& registrationKey, const Vector<std::pair<URL, ScriptBuffer>>& scripts)
     622{
     623    auto jobQueue = m_jobQueues.get(registrationKey);
     624    if (!jobQueue)
     625        return;
     626
     627    jobQueue->importedScriptsFetchFinished(jobDataIdentifier, scripts);
    565628}
    566629
  • trunk/Source/WebCore/workers/service/server/SWServer.h

    r293501 r293506  
    106106        WEBCORE_EXPORT Connection(SWServer&, Identifier);
    107107
    108         WEBCORE_EXPORT void finishFetchingScriptInServer(const ServiceWorkerJobDataIdentifier&, const ServiceWorkerRegistrationKey&, const WorkerFetchResult&);
     108        WEBCORE_EXPORT void finishFetchingScriptInServer(const ServiceWorkerJobDataIdentifier&, const ServiceWorkerRegistrationKey&, WorkerFetchResult&&);
    109109        WEBCORE_EXPORT void addServiceWorkerRegistrationInServer(ServiceWorkerRegistrationIdentifier);
    110110        WEBCORE_EXPORT void removeServiceWorkerRegistrationInServer(ServiceWorkerRegistrationIdentifier);
     
    119119        virtual void resolveUnregistrationJobInClient(ServiceWorkerJobIdentifier, const ServiceWorkerRegistrationKey&, bool registrationResult) = 0;
    120120        virtual void startScriptFetchInClient(ServiceWorkerJobIdentifier, const ServiceWorkerRegistrationKey&, FetchOptions::Cache) = 0;
     121        virtual void refreshImportedScripts(ServiceWorkerJobIdentifier, FetchOptions::Cache, const Vector<URL>&, ServiceWorkerJob::RefreshImportedScriptsCallback&&) = 0;
    121122
    122123        struct RegistrationReadyRequest {
     
    131132    };
    132133
    133     using SoftUpdateCallback = Function<void(ServiceWorkerJobData&& jobData, bool shouldRefreshCache, ResourceRequest&&, CompletionHandler<void(const WorkerFetchResult&)>&&)>;
     134    using SoftUpdateCallback = Function<void(ServiceWorkerJobData&& jobData, bool shouldRefreshCache, ResourceRequest&&, CompletionHandler<void(WorkerFetchResult&&)>&&)>;
    134135    using CreateContextConnectionCallback = Function<void(const WebCore::RegistrableDomain&, std::optional<ProcessIdentifier> requestingProcessIdentifier, std::optional<ScriptExecutionContextIdentifier>, CompletionHandler<void()>&&)>;
    135136    using AppBoundDomainsCallback = Function<void(CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&&)>;
     
    157158    void resolveUnregistrationJob(const ServiceWorkerJobData&, const ServiceWorkerRegistrationKey&, bool unregistrationResult);
    158159    void startScriptFetch(const ServiceWorkerJobData&, SWServerRegistration&);
     160    void refreshImportedScripts(const ServiceWorkerJobData&, SWServerRegistration&, const Vector<URL>&);
    159161
    160162    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);
     
    179181    SWOriginStore& originStore() { return m_originStore; }
    180182
     183    void refreshImportedScriptsFinished(const ServiceWorkerJobDataIdentifier&, const ServiceWorkerRegistrationKey&, const Vector<std::pair<URL, ScriptBuffer>>&);
    181184    void scriptContextFailedToStart(const std::optional<ServiceWorkerJobDataIdentifier>&, SWServerWorker&, const String& message);
    182185    void scriptContextStarted(const std::optional<ServiceWorkerJobDataIdentifier>&, SWServerWorker&);
     
    260263    void validateRegistrationDomain(WebCore::RegistrableDomain, ServiceWorkerJobType, bool, CompletionHandler<void(bool)>&&);
    261264
    262     void scriptFetchFinished(const ServiceWorkerJobDataIdentifier&, const ServiceWorkerRegistrationKey&, const WorkerFetchResult&);
     265    void scriptFetchFinished(const ServiceWorkerJobDataIdentifier&, const ServiceWorkerRegistrationKey&, WorkerFetchResult&&);
    263266
    264267    void didResolveRegistrationPromise(Connection*, const ServiceWorkerRegistrationKey&);
     
    283286    void updateAppInitiatedValueForWorkers(const ClientOrigin&, LastNavigationWasAppInitiated);
    284287    void whenImportIsCompletedIfNeeded(CompletionHandler<void()>&&);
     288
     289    ResourceRequest createScriptRequest(const URL&, const ServiceWorkerJobData&, SWServerRegistration&);
    285290
    286291    HashMap<SWServerConnectionIdentifier, std::unique_ptr<Connection>> m_connections;
  • trunk/Source/WebCore/workers/service/server/SWServerJobQueue.cpp

    r288938 r293506  
    7070}
    7171
    72 void SWServerJobQueue::scriptFetchFinished(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const WorkerFetchResult& result)
     72void SWServerJobQueue::scriptFetchFinished(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, WorkerFetchResult&& result)
    7373{
    7474    if (!isCurrentlyProcessingJob(jobDataIdentifier))
     
    102102    // text, then:
    103103    if (newestWorker && equalIgnoringFragmentIdentifier(newestWorker->scriptURL(), job.scriptURL) && newestWorker->type() == job.workerType && result.script == newestWorker->script() && doCertificatesMatch(result.certificateInfo, newestWorker->certificateInfo())) {
    104         RELEASE_LOG(ServiceWorker, "%p - SWServerJobQueue::scriptFetchFinished, script and certificate are matching for registrationID=%llu", this, registration->identifier().toUInt64());
     104
     105        auto scriptURLs = newestWorker->importedScriptURLs();
     106        if (!scriptURLs.isEmpty()) {
     107            m_workerFetchResult = WTFMove(result);
     108            m_server.refreshImportedScripts(job, *registration, scriptURLs);
     109            return;
     110        }
     111
    105112        // FIXME: for non classic scripts, check the script’s module record's [[ECMAScriptCode]].
    106113
    107         // Invoke Resolve Job Promise with job and registration.
    108         m_server.resolveRegistrationJob(job, registration->data(), ShouldNotifyWhenResolved::No);
    109 
    110         // Invoke Finish Job with job and abort these steps.
    111         finishCurrentJob();
    112         return;
    113     }
    114 
    115     // FIXME: Update all the imported scripts as per spec. For now, we just do as if there is none.
     114        RELEASE_LOG(ServiceWorker, "%p - SWServerJobQueue::scriptFetchFinished, script, certificate and imported scripts are matching for registrationID=%llu", this, registration->identifier().toUInt64());
     115        scriptAndImportedScriptsFetchFinished(job, *registration);
     116        return;
     117    }
    116118
    117119    m_server.updateWorker(job.identifier(), *registration, job.scriptURL, result.script, result.certificateInfo, result.contentSecurityPolicy, result.crossOriginEmbedderPolicy, result.referrerPolicy, job.workerType, { }, job.serviceWorkerPageIdentifier());
     120}
     121
     122void SWServerJobQueue::importedScriptsFetchFinished(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const Vector<std::pair<URL, ScriptBuffer>>& importedScripts)
     123{
     124    if (!isCurrentlyProcessingJob(jobDataIdentifier))
     125        return;
     126
     127    auto& job = firstJob();
     128
     129    auto* registration = m_server.getRegistration(m_registrationKey);
     130    if (!registration)
     131        return;
     132
     133    auto* newestWorker = registration->getNewestWorker();
     134    if (newestWorker && newestWorker->matchingImportedScripts(importedScripts)) {
     135        RELEASE_LOG(ServiceWorker, "%p - SWServerJobQueue::importedScriptsFetchFinished, script, certificate and imported scripts are matching for registrationID=%llu", this, registration->identifier().toUInt64());
     136        scriptAndImportedScriptsFetchFinished(job, *registration);
     137        return;
     138    }
     139
     140    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());
     141}
     142
     143void SWServerJobQueue::scriptAndImportedScriptsFetchFinished(const ServiceWorkerJobData& job, SWServerRegistration& registration)
     144{
     145    // Invoke Resolve Job Promise with job and registration.
     146    m_server.resolveRegistrationJob(job, registration.data(), ShouldNotifyWhenResolved::No);
     147
     148    // Invoke Finish Job with job and abort these steps.
     149    finishCurrentJob();
    118150}
    119151
  • trunk/Source/WebCore/workers/service/server/SWServerJobQueue.h

    r288938 r293506  
    3131#include "ServiceWorkerJobData.h"
    3232#include "Timer.h"
     33#include "WorkerFetchResult.h"
    3334#include <wtf/Deque.h>
    3435
     
    3637
    3738class SWServerWorker;
     39class ServiceWorkerJob;
    3840struct WorkerFetchResult;
    3941
     
    5254    void runNextJob();
    5355
    54     void scriptFetchFinished(const ServiceWorkerJobDataIdentifier&, const WorkerFetchResult&);
     56    void scriptFetchFinished(const ServiceWorkerJobDataIdentifier&, WorkerFetchResult&&);
     57    void importedScriptsFetchFinished(const ServiceWorkerJobDataIdentifier&, const Vector<std::pair<URL, ScriptBuffer>>&);
    5558    void scriptContextFailedToStart(const ServiceWorkerJobDataIdentifier&, ServiceWorkerIdentifier, const String& message);
    5659    void scriptContextStarted(const ServiceWorkerJobDataIdentifier&, ServiceWorkerIdentifier);
     
    7578
    7679    void removeAllJobsMatching(const Function<bool(ServiceWorkerJobData&)>&);
     80    void scriptAndImportedScriptsFetchFinished(const ServiceWorkerJobData&, SWServerRegistration&);
    7781
    7882    Deque<ServiceWorkerJobData> m_jobQueue;
     
    8185    SWServer& m_server;
    8286    ServiceWorkerRegistrationKey m_registrationKey;
     87    WorkerFetchResult m_workerFetchResult;
    8388};
    8489
  • trunk/Source/WebCore/workers/service/server/SWServerWorker.cpp

    r293195 r293506  
    428428}
    429429
     430Vector<URL> SWServerWorker::importedScriptURLs() const
     431{
     432    return copyToVector(m_scriptResourceMap.keys());
     433}
     434
     435bool SWServerWorker::matchingImportedScripts(const Vector<std::pair<URL, ScriptBuffer>>& scripts) const
     436{
     437    for (auto& script : scripts) {
     438        auto iterator = m_scriptResourceMap.find(script.first);
     439        if (iterator == m_scriptResourceMap.end() || iterator->value.script != script.second)
     440            return false;
     441    }
     442    return true;
     443}
     444
    430445} // namespace WebCore
    431446
  • trunk/Source/WebCore/workers/service/server/SWServerWorker.h

    r293195 r293506  
    145145    WEBCORE_EXPORT bool isClientActiveServiceWorker(ScriptExecutionContextIdentifier) const;
    146146
     147    Vector<URL> importedScriptURLs() const;
     148    const MemoryCompactRobinHoodHashMap<URL, ServiceWorkerContextData::ImportedScript>& scriptResourceMap() const { return m_scriptResourceMap; }
     149    bool matchingImportedScripts(const Vector<std::pair<URL, ScriptBuffer>>&) const;
     150
    147151private:
    148152    SWServerWorker(SWServer&, SWServerRegistration&, const URL&, const ScriptBuffer&, const CertificateInfo&, const ContentSecurityPolicyResponseHeaders&, const CrossOriginEmbedderPolicy&, String&& referrerPolicy, WorkerType, ServiceWorkerIdentifier, MemoryCompactRobinHoodHashMap<URL, ServiceWorkerContextData::ImportedScript>&&);
  • trunk/Source/WebKit/ChangeLog

    r293502 r293506  
     12022-04-27  Youenn Fablet  <youenn@apple.com>
     2
     3        service worker update should refresh imported scripts in addition to the main script
     4        https://bugs.webkit.org/show_bug.cgi?id=239657
     5
     6        Reviewed by Chris Dumez.
     7
     8        * NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.h:
     9        * NetworkProcess/ServiceWorker/WebSWServerConnection.cpp:
     10        * NetworkProcess/ServiceWorker/WebSWServerConnection.h:
     11        * WebProcess/Storage/WebSWClientConnection.messages.in:
     12
    1132022-04-27  Youenn Fablet  <youenn@apple.com>
    214
  • trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.h

    r289018 r293506  
    5151    WTF_MAKE_FAST_ALLOCATED;
    5252public:
    53     using Handler = CompletionHandler<void(const WebCore::WorkerFetchResult&)>;
     53    using Handler = CompletionHandler<void(WebCore::WorkerFetchResult&&)>;
    5454    static void start(NetworkSession*, WebCore::ServiceWorkerJobData&&, bool shouldRefreshCache, WebCore::ResourceRequest&&, Handler&&);
    5555
  • trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp

    r293501 r293506  
    135135}
    136136
     137void WebSWServerConnection::refreshImportedScripts(ServiceWorkerJobIdentifier jobIdentifier, FetchOptions::Cache cachePolicy, const Vector<URL>& urls, ServiceWorkerJob::RefreshImportedScriptsCallback&& callback)
     138{
     139    sendWithAsyncReply(Messages::WebSWClientConnection::RefreshImportedScripts(jobIdentifier, cachePolicy, urls), WTFMove(callback));
     140}
     141
    137142void WebSWServerConnection::updateRegistrationStateInClient(ServiceWorkerRegistrationIdentifier identifier, ServiceWorkerRegistrationState state, const std::optional<ServiceWorkerData>& serviceWorkerData)
    138143{
  • trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.h

    r293501 r293506  
    9797    void resolveUnregistrationJobInClient(WebCore::ServiceWorkerJobIdentifier, const WebCore::ServiceWorkerRegistrationKey&, bool unregistrationResult) final;
    9898    void startScriptFetchInClient(WebCore::ServiceWorkerJobIdentifier, const WebCore::ServiceWorkerRegistrationKey&, WebCore::FetchOptions::Cache) final;
     99    void refreshImportedScripts(WebCore::ServiceWorkerJobIdentifier, WebCore::FetchOptions::Cache, const Vector<URL>&, WebCore::ServiceWorkerJob::RefreshImportedScriptsCallback&&);
    99100    void updateRegistrationStateInClient(WebCore::ServiceWorkerRegistrationIdentifier, WebCore::ServiceWorkerRegistrationState, const std::optional<WebCore::ServiceWorkerData>&) final;
    100101    void updateWorkerStateInClient(WebCore::ServiceWorkerIdentifier, WebCore::ServiceWorkerState) final;
  • trunk/Source/WebKit/WebProcess/Storage/WebSWClientConnection.messages.in

    r292861 r293506  
    2828    RegistrationJobResolvedInServer(WebCore::ServiceWorkerJobIdentifier jobDataIdentifier, struct WebCore::ServiceWorkerRegistrationData registration, enum:bool WebCore::ShouldNotifyWhenResolved shouldNotifyWhenResolved)
    2929    StartScriptFetchForServer(WebCore::ServiceWorkerJobIdentifier jobDataIdentifier, WebCore::ServiceWorkerRegistrationKey registrationKey, WebCore::FetchOptions::Cache cachePolicy)
     30    RefreshImportedScripts(WebCore::ServiceWorkerJobIdentifier jobDataIdentifier, WebCore::FetchOptions::Cache cachePolicy, Vector<URL> urls) -> (Vector<std::pair<URL, WebCore::ScriptBuffer>> results);
    3031    UpdateRegistrationState(WebCore::ServiceWorkerRegistrationIdentifier identifier, enum:uint8_t WebCore::ServiceWorkerRegistrationState state, std::optional<WebCore::ServiceWorkerData> serviceWorkerIdentifier)
    3132    UpdateWorkerState(WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, enum:uint8_t WebCore::ServiceWorkerState state)
Note: See TracChangeset for help on using the changeset viewer.