Changeset 225537 in webkit


Ignore:
Timestamp:
Dec 5, 2017 1:51:42 PM (6 years ago)
Author:
commit-queue@webkit.org
Message:

Implement https://w3c.github.io/ServiceWorker/#clients-claim
https://bugs.webkit.org/show_bug.cgi?id=180261

Patch by Youenn Fablet <youenn@apple.com> on 2017-12-05
Reviewed by Chris Dumez.

LayoutTests/imported/w3c:

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

Source/WebCore:

Test: http/tests/workers/service/serviceworkerclients-claim.https.html

Implement claim by going to the storage process and then iterate over clients to see whether active worker can be set.
Update SWServerWorker to call registration tryClear/tryActivate whenever a service worker has no pending event.

  • workers/service/ServiceWorkerClients.cpp:

(WebCore::ServiceWorkerClients::claim):

  • workers/service/context/SWContextManager.h:
  • workers/service/server/SWServer.cpp:

(WebCore::SWServer::claim):
(WebCore::SWServer::doRegistrationMatching):
(WebCore::SWServer::doRegistrationMatching const): Deleted.

  • workers/service/server/SWServer.h:

(WebCore::SWServer::Connection::doRegistrationMatching):

  • workers/service/server/SWServerRegistration.cpp:

(WebCore::SWServerRegistration::controlClient):

  • workers/service/server/SWServerRegistration.h:
  • workers/service/server/SWServerToContextConnection.cpp:

(WebCore::SWServerToContextConnection::claim):

  • workers/service/server/SWServerToContextConnection.h:
  • workers/service/server/SWServerWorker.cpp:

(WebCore::SWServerWorker::claim):

  • workers/service/server/SWServerWorker.h:

Source/WebKit:

Add IPC plumbery for clients claim between ServiceWorker process and Storage process.

  • StorageProcess/ServiceWorker/WebSWServerToContextConnection.cpp:

(WebKit::WebSWServerToContextConnection::claimCompleted):

  • StorageProcess/ServiceWorker/WebSWServerToContextConnection.h:
  • StorageProcess/ServiceWorker/WebSWServerToContextConnection.messages.in:
  • WebProcess/Storage/WebSWContextManagerConnection.cpp:

(WebKit::WebSWContextManagerConnection::claim):
(WebKit::WebSWContextManagerConnection::claimCompleted):

  • WebProcess/Storage/WebSWContextManagerConnection.h:
  • WebProcess/Storage/WebSWContextManagerConnection.messages.in:

LayoutTests:

  • http/tests/workers/service/serviceworkerclients-claim-worker.js: Added.
  • http/tests/workers/service/serviceworkerclients-claim.https-expected.txt: Added.
  • http/tests/workers/service/serviceworkerclients-claim.https.html: Added.
Location:
trunk
Files:
3 added
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r225532 r225537  
     12017-12-05  Youenn Fablet  <youenn@apple.com>
     2
     3        Implement https://w3c.github.io/ServiceWorker/#clients-claim
     4        https://bugs.webkit.org/show_bug.cgi?id=180261
     5
     6        Reviewed by Chris Dumez.
     7
     8        * http/tests/workers/service/serviceworkerclients-claim-worker.js: Added.
     9        * http/tests/workers/service/serviceworkerclients-claim.https-expected.txt: Added.
     10        * http/tests/workers/service/serviceworkerclients-claim.https.html: Added.
     11
    1122017-12-05  Youenn Fablet  <youenn@apple.com>
    213
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r225532 r225537  
     12017-12-05  Youenn Fablet  <youenn@apple.com>
     2
     3        Implement https://w3c.github.io/ServiceWorker/#clients-claim
     4        https://bugs.webkit.org/show_bug.cgi?id=180261
     5
     6        Reviewed by Chris Dumez.
     7
     8        * web-platform-tests/service-workers/service-worker/activation.https-expected.txt:
     9
    1102017-12-05  Youenn Fablet  <youenn@apple.com>
    211
  • trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/activation.https-expected.txt

    r225513 r225537  
    11
    22
    3 FAIL loss of controllees triggers activation assert_not_equals: got disallowed value null
    4 FAIL finishing a request triggers activation assert_not_equals: got disallowed value null
    5 FAIL skipWaiting bypasses no controllee requirement assert_not_equals: got disallowed value null
    6 FAIL finishing a request triggers unregister assert_not_equals: got disallowed value null
     3PASS loss of controllees triggers activation
     4PASS finishing a request triggers activation
     5PASS skipWaiting bypasses no controllee requirement
     6FAIL finishing a request triggers unregister assert_equals: expected null but got object "[object ServiceWorker]"
    77
  • trunk/Source/WebCore/ChangeLog

    r225535 r225537  
     12017-12-05  Youenn Fablet  <youenn@apple.com>
     2
     3        Implement https://w3c.github.io/ServiceWorker/#clients-claim
     4        https://bugs.webkit.org/show_bug.cgi?id=180261
     5
     6        Reviewed by Chris Dumez.
     7
     8        Test: http/tests/workers/service/serviceworkerclients-claim.https.html
     9
     10        Implement claim by going to the storage process and then iterate over clients to see whether active worker can be set.
     11        Update SWServerWorker to call registration tryClear/tryActivate whenever a service worker has no pending event.
     12
     13        * workers/service/ServiceWorkerClients.cpp:
     14        (WebCore::ServiceWorkerClients::claim):
     15        * workers/service/context/SWContextManager.h:
     16        * workers/service/server/SWServer.cpp:
     17        (WebCore::SWServer::claim):
     18        (WebCore::SWServer::doRegistrationMatching):
     19        (WebCore::SWServer::doRegistrationMatching const): Deleted.
     20        * workers/service/server/SWServer.h:
     21        (WebCore::SWServer::Connection::doRegistrationMatching):
     22        * workers/service/server/SWServerRegistration.cpp:
     23        (WebCore::SWServerRegistration::controlClient):
     24        * workers/service/server/SWServerRegistration.h:
     25        * workers/service/server/SWServerToContextConnection.cpp:
     26        (WebCore::SWServerToContextConnection::claim):
     27        * workers/service/server/SWServerToContextConnection.h:
     28        * workers/service/server/SWServerWorker.cpp:
     29        (WebCore::SWServerWorker::claim):
     30        * workers/service/server/SWServerWorker.h:
     31
    1322017-12-05  Per Arne Vollan  <pvollan@apple.com>
    233
  • trunk/Source/WebCore/workers/service/SWClientConnection.cpp

    r225513 r225537  
    219219            continue;
    220220
    221         ASSERT(client->activeServiceWorker());
    222         ASSERT(client->activeServiceWorker()->identifier() != newController.identifier);
     221        ASSERT(!client->activeServiceWorker() || client->activeServiceWorker()->identifier() != newController.identifier);
    223222        client->setActiveServiceWorker(ServiceWorker::getOrCreate(*client, ServiceWorkerData { newController }));
    224223        if (auto* container = client->serviceWorkerContainer())
  • trunk/Source/WebCore/workers/service/ServiceWorkerClients.cpp

    r225452 r225537  
    108108}
    109109
    110 void ServiceWorkerClients::claim(ScriptExecutionContext&, Ref<DeferredPromise>&& promise)
     110void ServiceWorkerClients::claim(ScriptExecutionContext& context, Ref<DeferredPromise>&& promise)
    111111{
    112     promise->reject(Exception { NotSupportedError, ASCIILiteral("clients.claim() is not yet supported") });
     112    auto& serviceWorkerGlobalScope = downcast<ServiceWorkerGlobalScope>(context);
     113
     114    auto serviceWorkerIdentifier = serviceWorkerGlobalScope.thread().identifier();
     115
     116    if (!serviceWorkerGlobalScope.registration().active() || serviceWorkerGlobalScope.registration().active()->identifier() != serviceWorkerIdentifier) {
     117        promise->reject(Exception { InvalidStateError, ASCIILiteral("Service worker is not active") });
     118        return;
     119    }
     120
     121    auto promisePointer = promise.ptr();
     122    m_pendingPromises.add(promisePointer, WTFMove(promise));
     123
     124    callOnMainThread([promisePointer, serviceWorkerIdentifier] () mutable {
     125        auto connection = SWContextManager::singleton().connection();
     126        connection->claim(serviceWorkerIdentifier, [promisePointer, serviceWorkerIdentifier] () mutable {
     127            SWContextManager::singleton().postTaskToServiceWorker(serviceWorkerIdentifier, [promisePointer] (auto& scope) mutable {
     128                if (auto promise = scope.clients().m_pendingPromises.take(promisePointer))
     129                    promise.value()->resolve();
     130            });
     131        });
     132    });
    113133}
    114134
  • trunk/Source/WebCore/workers/service/context/SWContextManager.h

    r225462 r225537  
    6060        virtual void findClientByIdentifier(ServiceWorkerIdentifier, ServiceWorkerClientIdentifier, FindClientByIdentifierCallback&&) = 0;
    6161        virtual void matchAll(ServiceWorkerIdentifier, const ServiceWorkerClientQueryOptions&, ServiceWorkerClientsMatchAllCallback&&) = 0;
     62        virtual void claim(ServiceWorkerIdentifier, WTF::CompletionHandler<void()>&&) = 0;
    6263    };
    6364
  • trunk/Source/WebCore/workers/service/server/SWServer.cpp

    r225533 r225537  
    345345}
    346346
     347void SWServer::claim(SWServerWorker& worker)
     348{
     349    auto& origin = worker.origin();
     350    auto iterator = m_clients.find(origin);
     351    if (iterator == m_clients.end())
     352        return;
     353
     354    auto& clients = iterator->value.clients;
     355    for (auto& client : clients) {
     356        auto* registration = doRegistrationMatching(origin.topOrigin, client.data.url);
     357        if (!(registration && registration->key() == worker.registrationKey()))
     358            continue;
     359
     360        auto result = m_clientToControllingWorker.add(client.identifier, worker.identifier());
     361        if (!result.isNewEntry) {
     362            if (result.iterator->value == worker.identifier())
     363                continue;
     364            if (auto* controllingRegistration = registrationFromServiceWorkerIdentifier(result.iterator->value))
     365                controllingRegistration->removeClientUsingRegistration(client.identifier);
     366            result.iterator->value = worker.identifier();
     367        }
     368        registration->controlClient(client.identifier);
     369    }
     370}
     371
    347372void SWServer::didResolveRegistrationPromise(Connection& connection, const ServiceWorkerRegistrationKey& registrationKey)
    348373{
     
    567592}
    568593
    569 const SWServerRegistration* SWServer::doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL) const
    570 {
    571     const SWServerRegistration* selectedRegistration = nullptr;
     594SWServerRegistration* SWServer::doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL)
     595{
     596    SWServerRegistration* selectedRegistration = nullptr;
    572597    for (auto& registration : m_registrations.values()) {
    573598        if (!registration->key().isMatching(topOrigin, clientURL))
  • trunk/Source/WebCore/workers/service/server/SWServer.h

    r225531 r225537  
    7575
    7676        WEBCORE_EXPORT void didResolveRegistrationPromise(const ServiceWorkerRegistrationKey&);
    77         const SWServerRegistration* doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL) const { return m_server.doRegistrationMatching(topOrigin, clientURL); }
     77        SWServerRegistration* doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL) { return m_server.doRegistrationMatching(topOrigin, clientURL); }
    7878        void resolveRegistrationReadyRequests(SWServerRegistration&);
    7979
     
    151151    std::optional<ServiceWorkerClientData> findClientByIdentifier(const ClientOrigin&, ServiceWorkerClientIdentifier);
    152152    void matchAll(SWServerWorker&, const ServiceWorkerClientQueryOptions&, ServiceWorkerClientsMatchAllCallback&&);
     153    void claim(SWServerWorker&);
    153154
    154155    WEBCORE_EXPORT void serverToContextConnectionCreated();
     
    178179    void removeClientServiceWorkerRegistration(Connection&, ServiceWorkerRegistrationIdentifier);
    179180
    180     WEBCORE_EXPORT const SWServerRegistration* doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL) const;
     181    WEBCORE_EXPORT SWServerRegistration* doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL);
    181182
    182183    void installContextData(const ServiceWorkerContextData&);
  • trunk/Source/WebCore/workers/service/server/SWServerRegistration.cpp

    r225531 r225537  
    301301}
    302302
     303void SWServerRegistration::controlClient(ServiceWorkerClientIdentifier identifier)
     304{
     305    ASSERT(activeWorker());
     306
     307    addClientUsingRegistration(identifier);
     308
     309    HashSet<DocumentIdentifier> identifiers;
     310    identifiers.add(identifier.contextIdentifier);
     311    m_server.getConnection(identifier.serverConnectionIdentifier)->notifyClientsOfControllerChange(identifiers, activeWorker()->data());
     312}
     313
    303314void SWServerRegistration::setIsUninstalling(bool value)
    304315{
  • trunk/Source/WebCore/workers/service/server/SWServerRegistration.h

    r225531 r225537  
    8181
    8282    void notifyClientsOfControllerChange();
     83    void controlClient(ServiceWorkerClientIdentifier);
    8384
    8485    void clear();
  • trunk/Source/WebCore/workers/service/server/SWServerToContextConnection.cpp

    r225460 r225537  
    124124}
    125125
     126void SWServerToContextConnection::claim(uint64_t requestIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier)
     127{
     128    if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier)) {
     129        worker->claim();
     130        globalServerToContextConnection()->claimCompleted(requestIdentifier);
     131    }
     132}
     133
    126134void SWServerToContextConnection::skipWaiting(ServiceWorkerIdentifier serviceWorkerIdentifier, uint64_t callbackID)
    127135{
  • trunk/Source/WebCore/workers/service/server/SWServerToContextConnection.h

    r225460 r225537  
    5656    virtual void findClientByIdentifierCompleted(uint64_t requestIdentifier, const std::optional<ServiceWorkerClientData>&, bool hasSecurityError) = 0;
    5757    virtual void matchAllCompleted(uint64_t requestIdentifier, const Vector<ServiceWorkerClientInformation>&) = 0;
     58    virtual void claimCompleted(uint64_t requestIdentifier) = 0;
    5859    virtual void didFinishSkipWaiting(uint64_t callbackID) = 0;
    5960
     
    6869    WEBCORE_EXPORT void findClientByIdentifier(uint64_t clientIdRequestIdentifier, ServiceWorkerIdentifier, ServiceWorkerClientIdentifier);
    6970    WEBCORE_EXPORT void matchAll(uint64_t requestIdentifier, ServiceWorkerIdentifier, const ServiceWorkerClientQueryOptions&);
     71    WEBCORE_EXPORT void claim(uint64_t requestIdentifier, ServiceWorkerIdentifier);
    7072
    7173    static SWServerToContextConnection* connectionForIdentifier(SWServerToContextConnectionIdentifier);
  • trunk/Source/WebCore/workers/service/server/SWServerWorker.cpp

    r225460 r225537  
    117117}
    118118
     119void SWServerWorker::claim()
     120{
     121    return m_server.claim(*this);
     122}
     123
    119124void SWServerWorker::skipWaiting()
    120125{
     
    126131}
    127132
     133void SWServerWorker::setHasPendingEvents(bool hasPendingEvents)
     134{
     135    if (m_hasPendingEvents == hasPendingEvents)
     136        return;
     137
     138    m_hasPendingEvents = hasPendingEvents;
     139    if (m_hasPendingEvents)
     140        return;
     141
     142    // Do tryClear/tryActivate, as per https://w3c.github.io/ServiceWorker/#wait-until-method.
     143    auto* registration = m_server.getRegistration(m_registrationKey);
     144    ASSERT(registration);
     145    if (registration->isUninstalling() && registration->tryClear())
     146        return;
     147    registration->tryActivate();
     148}
     149
    128150} // namespace WebCore
    129151
  • trunk/Source/WebCore/workers/service/server/SWServerWorker.h

    r225460 r225537  
    8282
    8383    bool hasPendingEvents() const { return m_hasPendingEvents; }
    84     void setHasPendingEvents(bool value) { m_hasPendingEvents = value; }
     84    void setHasPendingEvents(bool);
    8585
    8686    void scriptContextFailedToStart(const std::optional<ServiceWorkerJobDataIdentifier>&, const String& message);
     
    9191    std::optional<ServiceWorkerClientData> findClientByIdentifier(ServiceWorkerClientIdentifier);
    9292    void matchAll(const ServiceWorkerClientQueryOptions&, ServiceWorkerClientsMatchAllCallback&&);
     93    void claim();
    9394
    9495    void skipWaiting();
  • trunk/Source/WebKit/ChangeLog

    r225531 r225537  
     12017-12-05  Youenn Fablet  <youenn@apple.com>
     2
     3        Implement https://w3c.github.io/ServiceWorker/#clients-claim
     4        https://bugs.webkit.org/show_bug.cgi?id=180261
     5
     6        Reviewed by Chris Dumez.
     7
     8        Add IPC plumbery for clients claim between ServiceWorker process and Storage process.
     9
     10        * StorageProcess/ServiceWorker/WebSWServerToContextConnection.cpp:
     11        (WebKit::WebSWServerToContextConnection::claimCompleted):
     12        * StorageProcess/ServiceWorker/WebSWServerToContextConnection.h:
     13        * StorageProcess/ServiceWorker/WebSWServerToContextConnection.messages.in:
     14        * WebProcess/Storage/WebSWContextManagerConnection.cpp:
     15        (WebKit::WebSWContextManagerConnection::claim):
     16        (WebKit::WebSWContextManagerConnection::claimCompleted):
     17        * WebProcess/Storage/WebSWContextManagerConnection.h:
     18        * WebProcess/Storage/WebSWContextManagerConnection.messages.in:
     19
    1202017-12-05  Chris Dumez  <cdumez@apple.com>
    221
  • trunk/Source/WebKit/StorageProcess/ServiceWorker/WebSWServerToContextConnection.cpp

    r225460 r225537  
    9292}
    9393
     94void WebSWServerToContextConnection::claimCompleted(uint64_t requestIdentifier)
     95{
     96    send(Messages::WebSWContextManagerConnection::ClaimCompleted { requestIdentifier });
     97}
     98
    9499void WebSWServerToContextConnection::didFinishSkipWaiting(uint64_t callbackID)
    95100{
  • trunk/Source/WebKit/StorageProcess/ServiceWorker/WebSWServerToContextConnection.h

    r225460 r225537  
    6363    void findClientByIdentifierCompleted(uint64_t requestIdentifier, const std::optional<WebCore::ServiceWorkerClientData>&, bool hasSecurityError) final;
    6464    void matchAllCompleted(uint64_t requestIdentifier, const Vector<WebCore::ServiceWorkerClientInformation>&) final;
     65    void claimCompleted(uint64_t requestIdentifier) final;
    6566    void didFinishSkipWaiting(uint64_t callbackID) final;
    6667
  • trunk/Source/WebKit/StorageProcess/ServiceWorker/WebSWServerToContextConnection.messages.in

    r225460 r225537  
    3535    FindClientByIdentifier(uint64_t requestIdentifier, WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, struct WebCore::ServiceWorkerClientIdentifier clientIdentifier);
    3636    MatchAll(uint64_t matchAllRequestIdentifier, WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, struct WebCore::ServiceWorkerClientQueryOptions options);
     37    Claim(uint64_t claimRequestIdentifier, WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier);
    3738}
    3839
  • trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.cpp

    r225462 r225537  
    246246}
    247247
     248void WebSWContextManagerConnection::claim(WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, CompletionHandler<void()>&& callback)
     249{
     250    auto requestIdentifier = ++m_previousRequestIdentifier;
     251    m_claimRequests.add(requestIdentifier, WTFMove(callback));
     252    m_connectionToStorageProcess->send(Messages::WebSWServerToContextConnection::Claim { requestIdentifier, serviceWorkerIdentifier }, 0);
     253}
     254
     255void WebSWContextManagerConnection::claimCompleted(uint64_t claimRequestIdentifier)
     256{
     257    if (auto callback = m_claimRequests.take(claimRequestIdentifier))
     258        callback();
     259}
     260
    248261void WebSWContextManagerConnection::didFinishSkipWaiting(uint64_t callbackID)
    249262{
  • trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.h

    r225462 r225537  
    6767    void findClientByIdentifier(WebCore::ServiceWorkerIdentifier, WebCore::ServiceWorkerClientIdentifier, FindClientByIdentifierCallback&&) final;
    6868    void matchAll(WebCore::ServiceWorkerIdentifier, const WebCore::ServiceWorkerClientQueryOptions&, WebCore::ServiceWorkerClientsMatchAllCallback&&) final;
     69    void claim(WebCore::ServiceWorkerIdentifier, WTF::CompletionHandler<void()>&&) final;
    6970    void skipWaiting(WebCore::ServiceWorkerIdentifier, WTF::Function<void()>&& callback) final;
    7071
     
    8182    void findClientByIdentifierCompleted(uint64_t requestIdentifier, std::optional<WebCore::ServiceWorkerClientData>&&, bool hasSecurityError);
    8283    void matchAllCompleted(uint64_t matchAllRequestIdentifier, Vector<WebCore::ServiceWorkerClientInformation>&&);
     84    void claimCompleted(uint64_t claimRequestIdentifier);
    8385    void didFinishSkipWaiting(uint64_t callbackID);
    8486
     
    8991    HashMap<uint64_t, FindClientByIdentifierCallback> m_findClientByIdentifierRequests;
    9092    HashMap<uint64_t, WebCore::ServiceWorkerClientsMatchAllCallback> m_matchAllRequests;
     93    HashMap<uint64_t, WTF::CompletionHandler<void()>> m_claimRequests;
    9194    HashMap<uint64_t, WTF::Function<void()>> m_skipWaitingRequests;
    9295    uint64_t m_previousRequestIdentifier { 0 };
  • trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.messages.in

    r225462 r225537  
    3434    FindClientByIdentifierCompleted(uint64_t clientIdRequestIdentifier, std::optional<WebCore::ServiceWorkerClientData> data, bool hasSecurityError)
    3535    MatchAllCompleted(uint64_t matchAllRequestIdentifier, Vector<WebCore::ServiceWorkerClientInformation> clientsData)
     36    ClaimCompleted(uint64_t claimRequestIdentifier)
    3637    DidFinishSkipWaiting(uint64_t callbackID)
    3738}
Note: See TracChangeset for help on using the changeset viewer.