Implement https://w3c.github.io/ServiceWorker/#clients-claim
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 5 Dec 2017 21:51:42 +0000 (21:51 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 5 Dec 2017 21:51:42 +0000 (21:51 +0000)
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.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@225537 268f45cc-cd09-0410-ab3c-d52691b4dbfc

25 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/workers/service/serviceworkerclients-claim-worker.js [new file with mode: 0644]
LayoutTests/http/tests/workers/service/serviceworkerclients-claim.https-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/workers/service/serviceworkerclients-claim.https.html [new file with mode: 0644]
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/activation.https-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/workers/service/SWClientConnection.cpp
Source/WebCore/workers/service/ServiceWorkerClients.cpp
Source/WebCore/workers/service/context/SWContextManager.h
Source/WebCore/workers/service/server/SWServer.cpp
Source/WebCore/workers/service/server/SWServer.h
Source/WebCore/workers/service/server/SWServerRegistration.cpp
Source/WebCore/workers/service/server/SWServerRegistration.h
Source/WebCore/workers/service/server/SWServerToContextConnection.cpp
Source/WebCore/workers/service/server/SWServerToContextConnection.h
Source/WebCore/workers/service/server/SWServerWorker.cpp
Source/WebCore/workers/service/server/SWServerWorker.h
Source/WebKit/ChangeLog
Source/WebKit/StorageProcess/ServiceWorker/WebSWServerToContextConnection.cpp
Source/WebKit/StorageProcess/ServiceWorker/WebSWServerToContextConnection.h
Source/WebKit/StorageProcess/ServiceWorker/WebSWServerToContextConnection.messages.in
Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.cpp
Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.h
Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.messages.in

index 1915b0b..7c19401 100644 (file)
@@ -1,5 +1,16 @@
 2017-12-05  Youenn Fablet  <youenn@apple.com>
 
+        Implement https://w3c.github.io/ServiceWorker/#clients-claim
+        https://bugs.webkit.org/show_bug.cgi?id=180261
+
+        Reviewed by Chris Dumez.
+
+        * 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.
+
+2017-12-05  Youenn Fablet  <youenn@apple.com>
+
         Unskip some more Service Worker tests
         https://bugs.webkit.org/show_bug.cgi?id=180428
 
diff --git a/LayoutTests/http/tests/workers/service/serviceworkerclients-claim-worker.js b/LayoutTests/http/tests/workers/service/serviceworkerclients-claim-worker.js
new file mode 100644 (file)
index 0000000..8de03f3
--- /dev/null
@@ -0,0 +1,34 @@
+self.addEventListener("fetch", async (event) => {
+    if (event.request.url.indexOf("pinkelephant") !== -1)
+        event.respondWith(new Response("PASS"));
+});
+
+var tryClaimPromise = self.clients.claim().then(() => {
+    return "FAIL: claim did not throw";
+}, (e) => {
+    return "PASS, received exception " + e;
+});
+
+async function doTest(event)
+{
+    if (event.data !== "start") {
+        event.source.postMessage("FAIL: received unexpected message from client");
+        return;
+    }
+
+    var result = await tryClaimPromise;
+    if (!result.startsWith("PASS")) {
+        event.source.postMessage(result);
+        return;
+    }
+
+    self.clients.claim().then(() => {
+        event.source.postMessage("CLAIMED");
+    }, () => {
+        event.source.postMessage("FAIL: received exception " + e);
+    });
+}
+
+
+self.addEventListener("message", doTest);
+
diff --git a/LayoutTests/http/tests/workers/service/serviceworkerclients-claim.https-expected.txt b/LayoutTests/http/tests/workers/service/serviceworkerclients-claim.https-expected.txt
new file mode 100644 (file)
index 0000000..f1aa21d
--- /dev/null
@@ -0,0 +1,4 @@
+
+PASS Setup worker 
+PASS Test self.clients.claim 
+
diff --git a/LayoutTests/http/tests/workers/service/serviceworkerclients-claim.https.html b/LayoutTests/http/tests/workers/service/serviceworkerclients-claim.https.html
new file mode 100644 (file)
index 0000000..9952621
--- /dev/null
@@ -0,0 +1,52 @@
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+var scope = "/workers/service/serviceworkerclients-claim.https.html";
+var activeWorker;
+
+promise_test(async (test) => {
+    var registration = await navigator.serviceWorker.getRegistration(scope);
+    if (registration && registration.scope === scope)
+        await registration.unregister();
+
+    var registration = await navigator.serviceWorker.register("serviceworkerclients-claim-worker.js", { scope : scope });
+    activeWorker = registration.active;
+    if (activeWorker)
+        return;
+    activeWorker = registration.installing;
+    return new Promise(resolve => {
+        activeWorker.addEventListener('statechange', () => {
+            if (activeWorker.state === "activated")
+                resolve();
+        });
+    });
+}, "Setup worker");
+
+promise_test(async (test) => {
+    var promise = new Promise((resolve, reject) => {
+        navigator.serviceWorker.addEventListener("message", test.step_func((event) => {
+            if (event.data === "CLAIMED") {
+                resolve();
+                return;
+            }
+            if (!event.data.startsWith("PASS")) {
+                reject(event.data);
+                return;
+            }
+        }));
+    });
+
+    activeWorker.postMessage("start");
+    await promise;
+
+    var response = await fetch("pinkelephant");
+    var text = await response.text();
+    assert_equals(text, "PASS");
+}, "Test self.clients.claim");
+</script>
+</body>
+</html>
index 3703d42..73b8527 100644 (file)
@@ -1,5 +1,14 @@
 2017-12-05  Youenn Fablet  <youenn@apple.com>
 
+        Implement https://w3c.github.io/ServiceWorker/#clients-claim
+        https://bugs.webkit.org/show_bug.cgi?id=180261
+
+        Reviewed by Chris Dumez.
+
+        * web-platform-tests/service-workers/service-worker/activation.https-expected.txt:
+
+2017-12-05  Youenn Fablet  <youenn@apple.com>
+
         Unskip some more Service Worker tests
         https://bugs.webkit.org/show_bug.cgi?id=180428
 
index fee4ab0..02387fc 100644 (file)
@@ -1,7 +1,7 @@
 
 
-FAIL loss of controllees triggers activation assert_not_equals: got disallowed value null
-FAIL finishing a request triggers activation assert_not_equals: got disallowed value null
-FAIL skipWaiting bypasses no controllee requirement assert_not_equals: got disallowed value null
-FAIL finishing a request triggers unregister assert_not_equals: got disallowed value null
+PASS loss of controllees triggers activation 
+PASS finishing a request triggers activation 
+PASS skipWaiting bypasses no controllee requirement 
+FAIL finishing a request triggers unregister assert_equals: expected null but got object "[object ServiceWorker]"
 
index fcc5357..95e8818 100644 (file)
@@ -1,3 +1,34 @@
+2017-12-05  Youenn Fablet  <youenn@apple.com>
+
+        Implement https://w3c.github.io/ServiceWorker/#clients-claim
+        https://bugs.webkit.org/show_bug.cgi?id=180261
+
+        Reviewed by Chris Dumez.
+
+        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:
+
 2017-12-05  Per Arne Vollan  <pvollan@apple.com>
 
         [Win] Scrollbars are sometimes not rendered in accelerated compositing mode.
index 6fe98f5..98a4229 100644 (file)
@@ -218,8 +218,7 @@ void SWClientConnection::notifyClientsOfControllerChange(const HashSet<DocumentI
         if (!client)
             continue;
 
-        ASSERT(client->activeServiceWorker());
-        ASSERT(client->activeServiceWorker()->identifier() != newController.identifier);
+        ASSERT(!client->activeServiceWorker() || client->activeServiceWorker()->identifier() != newController.identifier);
         client->setActiveServiceWorker(ServiceWorker::getOrCreate(*client, ServiceWorkerData { newController }));
         if (auto* container = client->serviceWorkerContainer())
             container->scheduleTaskToFireControllerChangeEvent();
index 4504f53..61687f9 100644 (file)
@@ -107,9 +107,29 @@ void ServiceWorkerClients::openWindow(ScriptExecutionContext&, const String& url
     promise->reject(Exception { NotSupportedError, ASCIILiteral("clients.openWindow() is not yet supported") });
 }
 
-void ServiceWorkerClients::claim(ScriptExecutionContext&, Ref<DeferredPromise>&& promise)
+void ServiceWorkerClients::claim(ScriptExecutionContext& context, Ref<DeferredPromise>&& promise)
 {
-    promise->reject(Exception { NotSupportedError, ASCIILiteral("clients.claim() is not yet supported") });
+    auto& serviceWorkerGlobalScope = downcast<ServiceWorkerGlobalScope>(context);
+
+    auto serviceWorkerIdentifier = serviceWorkerGlobalScope.thread().identifier();
+
+    if (!serviceWorkerGlobalScope.registration().active() || serviceWorkerGlobalScope.registration().active()->identifier() != serviceWorkerIdentifier) {
+        promise->reject(Exception { InvalidStateError, ASCIILiteral("Service worker is not active") });
+        return;
+    }
+
+    auto promisePointer = promise.ptr();
+    m_pendingPromises.add(promisePointer, WTFMove(promise));
+
+    callOnMainThread([promisePointer, serviceWorkerIdentifier] () mutable {
+        auto connection = SWContextManager::singleton().connection();
+        connection->claim(serviceWorkerIdentifier, [promisePointer, serviceWorkerIdentifier] () mutable {
+            SWContextManager::singleton().postTaskToServiceWorker(serviceWorkerIdentifier, [promisePointer] (auto& scope) mutable {
+                if (auto promise = scope.clients().m_pendingPromises.take(promisePointer))
+                    promise.value()->resolve();
+            });
+        });
+    });
 }
 
 } // namespace WebCore
index 5a14541..f4e0221 100644 (file)
@@ -59,6 +59,7 @@ public:
         using FindClientByIdentifierCallback = WTF::CompletionHandler<void(ExceptionOr<std::optional<ServiceWorkerClientData>>&&)>;
         virtual void findClientByIdentifier(ServiceWorkerIdentifier, ServiceWorkerClientIdentifier, FindClientByIdentifierCallback&&) = 0;
         virtual void matchAll(ServiceWorkerIdentifier, const ServiceWorkerClientQueryOptions&, ServiceWorkerClientsMatchAllCallback&&) = 0;
+        virtual void claim(ServiceWorkerIdentifier, WTF::CompletionHandler<void()>&&) = 0;
     };
 
     WEBCORE_EXPORT void setConnection(std::unique_ptr<Connection>&&);
index b3b09f1..1bcf979 100644 (file)
@@ -344,6 +344,31 @@ void SWServer::matchAll(SWServerWorker& worker, const ServiceWorkerClientQueryOp
     callback(WTFMove(clients));
 }
 
+void SWServer::claim(SWServerWorker& worker)
+{
+    auto& origin = worker.origin();
+    auto iterator = m_clients.find(origin);
+    if (iterator == m_clients.end())
+        return;
+
+    auto& clients = iterator->value.clients;
+    for (auto& client : clients) {
+        auto* registration = doRegistrationMatching(origin.topOrigin, client.data.url);
+        if (!(registration && registration->key() == worker.registrationKey()))
+            continue;
+
+        auto result = m_clientToControllingWorker.add(client.identifier, worker.identifier());
+        if (!result.isNewEntry) {
+            if (result.iterator->value == worker.identifier())
+                continue;
+            if (auto* controllingRegistration = registrationFromServiceWorkerIdentifier(result.iterator->value))
+                controllingRegistration->removeClientUsingRegistration(client.identifier);
+            result.iterator->value = worker.identifier();
+        }
+        registration->controlClient(client.identifier);
+    }
+}
+
 void SWServer::didResolveRegistrationPromise(Connection& connection, const ServiceWorkerRegistrationKey& registrationKey)
 {
     ASSERT_UNUSED(connection, m_connections.contains(connection.identifier()));
@@ -566,9 +591,9 @@ void SWServer::unregisterConnection(Connection& connection)
         registration->unregisterServerConnection(connection.identifier());
 }
 
-const SWServerRegistration* SWServer::doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL) const
+SWServerRegistration* SWServer::doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL)
 {
-    const SWServerRegistration* selectedRegistration = nullptr;
+    SWServerRegistration* selectedRegistration = nullptr;
     for (auto& registration : m_registrations.values()) {
         if (!registration->key().isMatching(topOrigin, clientURL))
             continue;
index 8f38010..3199a60 100644 (file)
@@ -74,7 +74,7 @@ public:
         Identifier identifier() const { return m_identifier; }
 
         WEBCORE_EXPORT void didResolveRegistrationPromise(const ServiceWorkerRegistrationKey&);
-        const SWServerRegistration* doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL) const { return m_server.doRegistrationMatching(topOrigin, clientURL); }
+        SWServerRegistration* doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL) { return m_server.doRegistrationMatching(topOrigin, clientURL); }
         void resolveRegistrationReadyRequests(SWServerRegistration&);
 
         // Messages to the client WebProcess
@@ -150,6 +150,7 @@ public:
     void workerContextTerminated(SWServerWorker&);
     std::optional<ServiceWorkerClientData> findClientByIdentifier(const ClientOrigin&, ServiceWorkerClientIdentifier);
     void matchAll(SWServerWorker&, const ServiceWorkerClientQueryOptions&, ServiceWorkerClientsMatchAllCallback&&);
+    void claim(SWServerWorker&);
 
     WEBCORE_EXPORT void serverToContextConnectionCreated();
     
@@ -177,7 +178,7 @@ private:
     void addClientServiceWorkerRegistration(Connection&, ServiceWorkerRegistrationIdentifier);
     void removeClientServiceWorkerRegistration(Connection&, ServiceWorkerRegistrationIdentifier);
 
-    WEBCORE_EXPORT const SWServerRegistration* doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL) const;
+    WEBCORE_EXPORT SWServerRegistration* doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL);
 
     void installContextData(const ServiceWorkerContextData&);
 
index f52770f..f06f0e5 100644 (file)
@@ -300,6 +300,17 @@ void SWServerRegistration::handleClientUnload()
     tryActivate();
 }
 
+void SWServerRegistration::controlClient(ServiceWorkerClientIdentifier identifier)
+{
+    ASSERT(activeWorker());
+
+    addClientUsingRegistration(identifier);
+
+    HashSet<DocumentIdentifier> identifiers;
+    identifiers.add(identifier.contextIdentifier);
+    m_server.getConnection(identifier.serverConnectionIdentifier)->notifyClientsOfControllerChange(identifiers, activeWorker()->data());
+}
+
 void SWServerRegistration::setIsUninstalling(bool value)
 {
     if (m_uninstalling == value)
index 762749a..dc4a4b0 100644 (file)
@@ -80,6 +80,7 @@ public:
     void unregisterServerConnection(SWServerConnectionIdentifier);
 
     void notifyClientsOfControllerChange();
+    void controlClient(ServiceWorkerClientIdentifier);
 
     void clear();
     bool tryClear();
index 231b9b4..b23af1c 100644 (file)
@@ -123,6 +123,14 @@ void SWServerToContextConnection::matchAll(uint64_t requestIdentifier, ServiceWo
     }
 }
 
+void SWServerToContextConnection::claim(uint64_t requestIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier)
+{
+    if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier)) {
+        worker->claim();
+        globalServerToContextConnection()->claimCompleted(requestIdentifier);
+    }
+}
+
 void SWServerToContextConnection::skipWaiting(ServiceWorkerIdentifier serviceWorkerIdentifier, uint64_t callbackID)
 {
     if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier))
index 1be87f5..d09b433 100644 (file)
@@ -55,6 +55,7 @@ public:
     virtual void syncTerminateWorker(ServiceWorkerIdentifier) = 0;
     virtual void findClientByIdentifierCompleted(uint64_t requestIdentifier, const std::optional<ServiceWorkerClientData>&, bool hasSecurityError) = 0;
     virtual void matchAllCompleted(uint64_t requestIdentifier, const Vector<ServiceWorkerClientInformation>&) = 0;
+    virtual void claimCompleted(uint64_t requestIdentifier) = 0;
     virtual void didFinishSkipWaiting(uint64_t callbackID) = 0;
 
     // Messages back from the SW host process
@@ -67,6 +68,7 @@ public:
     WEBCORE_EXPORT void workerTerminated(ServiceWorkerIdentifier);
     WEBCORE_EXPORT void findClientByIdentifier(uint64_t clientIdRequestIdentifier, ServiceWorkerIdentifier, ServiceWorkerClientIdentifier);
     WEBCORE_EXPORT void matchAll(uint64_t requestIdentifier, ServiceWorkerIdentifier, const ServiceWorkerClientQueryOptions&);
+    WEBCORE_EXPORT void claim(uint64_t requestIdentifier, ServiceWorkerIdentifier);
 
     static SWServerToContextConnection* connectionForIdentifier(SWServerToContextConnectionIdentifier);
 
index 8076714..5068b0d 100644 (file)
@@ -116,6 +116,11 @@ void SWServerWorker::matchAll(const ServiceWorkerClientQueryOptions& options, Se
     return m_server.matchAll(*this, options, WTFMove(callback));
 }
 
+void SWServerWorker::claim()
+{
+    return m_server.claim(*this);
+}
+
 void SWServerWorker::skipWaiting()
 {
     m_isSkipWaitingFlagSet = true;
@@ -125,6 +130,23 @@ void SWServerWorker::skipWaiting()
     registration->tryActivate();
 }
 
+void SWServerWorker::setHasPendingEvents(bool hasPendingEvents)
+{
+    if (m_hasPendingEvents == hasPendingEvents)
+        return;
+
+    m_hasPendingEvents = hasPendingEvents;
+    if (m_hasPendingEvents)
+        return;
+
+    // Do tryClear/tryActivate, as per https://w3c.github.io/ServiceWorker/#wait-until-method.
+    auto* registration = m_server.getRegistration(m_registrationKey);
+    ASSERT(registration);
+    if (registration->isUninstalling() && registration->tryClear())
+        return;
+    registration->tryActivate();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(SERVICE_WORKER)
index 3c5208e..fb8df84 100644 (file)
@@ -81,7 +81,7 @@ public:
     void setState(ServiceWorkerState state) { m_data.state = state; }
 
     bool hasPendingEvents() const { return m_hasPendingEvents; }
-    void setHasPendingEvents(bool value) { m_hasPendingEvents = value; }
+    void setHasPendingEvents(bool);
 
     void scriptContextFailedToStart(const std::optional<ServiceWorkerJobDataIdentifier>&, const String& message);
     void scriptContextStarted(const std::optional<ServiceWorkerJobDataIdentifier>&);
@@ -90,6 +90,7 @@ public:
     void contextTerminated();
     std::optional<ServiceWorkerClientData> findClientByIdentifier(ServiceWorkerClientIdentifier);
     void matchAll(const ServiceWorkerClientQueryOptions&, ServiceWorkerClientsMatchAllCallback&&);
+    void claim();
 
     void skipWaiting();
     bool isSkipWaitingFlagSet() const { return m_isSkipWaitingFlagSet; }
index 322a5cd..43212b1 100644 (file)
@@ -1,3 +1,22 @@
+2017-12-05  Youenn Fablet  <youenn@apple.com>
+
+        Implement https://w3c.github.io/ServiceWorker/#clients-claim
+        https://bugs.webkit.org/show_bug.cgi?id=180261
+
+        Reviewed by Chris Dumez.
+
+        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:
+
 2017-12-05  Chris Dumez  <cdumez@apple.com>
 
         Add support for ServiceWorkerContainer.prototype.ready
index a5a9bc9..1868e28 100644 (file)
@@ -91,6 +91,11 @@ void WebSWServerToContextConnection::matchAllCompleted(uint64_t requestIdentifie
     send(Messages::WebSWContextManagerConnection::MatchAllCompleted { requestIdentifier, clientsData });
 }
 
+void WebSWServerToContextConnection::claimCompleted(uint64_t requestIdentifier)
+{
+    send(Messages::WebSWContextManagerConnection::ClaimCompleted { requestIdentifier });
+}
+
 void WebSWServerToContextConnection::didFinishSkipWaiting(uint64_t callbackID)
 {
     send(Messages::WebSWContextManagerConnection::DidFinishSkipWaiting { callbackID });
index c640256..f839e67 100644 (file)
@@ -62,6 +62,7 @@ private:
     void syncTerminateWorker(WebCore::ServiceWorkerIdentifier) final;
     void findClientByIdentifierCompleted(uint64_t requestIdentifier, const std::optional<WebCore::ServiceWorkerClientData>&, bool hasSecurityError) final;
     void matchAllCompleted(uint64_t requestIdentifier, const Vector<WebCore::ServiceWorkerClientInformation>&) final;
+    void claimCompleted(uint64_t requestIdentifier) final;
     void didFinishSkipWaiting(uint64_t callbackID) final;
 
     Ref<IPC::Connection> m_ipcConnection;
index 101d3d4..3405a5a 100644 (file)
@@ -34,6 +34,7 @@ messages -> WebSWServerToContextConnection {
     WorkerTerminated(WebCore::ServiceWorkerIdentifier identifier);
     FindClientByIdentifier(uint64_t requestIdentifier, WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, struct WebCore::ServiceWorkerClientIdentifier clientIdentifier);
     MatchAll(uint64_t matchAllRequestIdentifier, WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, struct WebCore::ServiceWorkerClientQueryOptions options);
+    Claim(uint64_t claimRequestIdentifier, WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier);
 }
 
 #endif // ENABLE(SERVICE_WORKER)
index 6285123..a46e6be 100644 (file)
@@ -245,6 +245,19 @@ void WebSWContextManagerConnection::matchAllCompleted(uint64_t requestIdentifier
         callback(WTFMove(clientsData));
 }
 
+void WebSWContextManagerConnection::claim(WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, CompletionHandler<void()>&& callback)
+{
+    auto requestIdentifier = ++m_previousRequestIdentifier;
+    m_claimRequests.add(requestIdentifier, WTFMove(callback));
+    m_connectionToStorageProcess->send(Messages::WebSWServerToContextConnection::Claim { requestIdentifier, serviceWorkerIdentifier }, 0);
+}
+
+void WebSWContextManagerConnection::claimCompleted(uint64_t claimRequestIdentifier)
+{
+    if (auto callback = m_claimRequests.take(claimRequestIdentifier))
+        callback();
+}
+
 void WebSWContextManagerConnection::didFinishSkipWaiting(uint64_t callbackID)
 {
     if (auto callback = m_skipWaitingRequests.take(callbackID))
index 70750c3..e2953a1 100644 (file)
@@ -66,6 +66,7 @@ private:
     void workerTerminated(WebCore::ServiceWorkerIdentifier) final;
     void findClientByIdentifier(WebCore::ServiceWorkerIdentifier, WebCore::ServiceWorkerClientIdentifier, FindClientByIdentifierCallback&&) final;
     void matchAll(WebCore::ServiceWorkerIdentifier, const WebCore::ServiceWorkerClientQueryOptions&, WebCore::ServiceWorkerClientsMatchAllCallback&&) final;
+    void claim(WebCore::ServiceWorkerIdentifier, WTF::CompletionHandler<void()>&&) final;
     void skipWaiting(WebCore::ServiceWorkerIdentifier, WTF::Function<void()>&& callback) final;
 
     // IPC messages.
@@ -80,6 +81,7 @@ private:
     void syncTerminateWorker(WebCore::ServiceWorkerIdentifier, Ref<Messages::WebSWContextManagerConnection::SyncTerminateWorker::DelayedReply>&&);
     void findClientByIdentifierCompleted(uint64_t requestIdentifier, std::optional<WebCore::ServiceWorkerClientData>&&, bool hasSecurityError);
     void matchAllCompleted(uint64_t matchAllRequestIdentifier, Vector<WebCore::ServiceWorkerClientInformation>&&);
+    void claimCompleted(uint64_t claimRequestIdentifier);
     void didFinishSkipWaiting(uint64_t callbackID);
 
     Ref<IPC::Connection> m_connectionToStorageProcess;
@@ -88,6 +90,7 @@ private:
 
     HashMap<uint64_t, FindClientByIdentifierCallback> m_findClientByIdentifierRequests;
     HashMap<uint64_t, WebCore::ServiceWorkerClientsMatchAllCallback> m_matchAllRequests;
+    HashMap<uint64_t, WTF::CompletionHandler<void()>> m_claimRequests;
     HashMap<uint64_t, WTF::Function<void()>> m_skipWaitingRequests;
     uint64_t m_previousRequestIdentifier { 0 };
 };
index 821dcdf..3982b45 100644 (file)
@@ -33,6 +33,7 @@ messages -> WebSWContextManagerConnection {
     SyncTerminateWorker(WebCore::ServiceWorkerIdentifier identifier) -> () Delayed
     FindClientByIdentifierCompleted(uint64_t clientIdRequestIdentifier, std::optional<WebCore::ServiceWorkerClientData> data, bool hasSecurityError)
     MatchAllCompleted(uint64_t matchAllRequestIdentifier, Vector<WebCore::ServiceWorkerClientInformation> clientsData)
+    ClaimCompleted(uint64_t claimRequestIdentifier)
     DidFinishSkipWaiting(uint64_t callbackID)
 }